Skip to main content
GameDev.net gamedev.net
🔒 Locked

[.net] delegates and return values

Started by Quat Feb 26, 2008 at 12:16 PM 2 replies 1k views
Original Post
Quat
Quat
What if you add several functions to a delegate, and the functions have return values? When you invoke the delegate, each function in its invocation list is called, but how can you capture the return values? Also, if you are adding multiple functions to a delegate, is this the way you do it (first set the delegate to null, then use +=):

    // Define the delegate type.
    public delegate float BinaryOp(float x, float y);

    class Program
    {
        static void Main(string[] args)
        {
            Program p = new Program();

            BinaryOp f = new BinaryOp(p.Add);
            BinaryOp g = new BinaryOp(p.Sub);
            BinaryOp h = new BinaryOp(p.Mul);

            BinaryOp funcList = null;
            funcList += f;
            funcList += g;
            funcList += h;

            funcList(2,3);
        }

        float Add(float x, float y)
        {
            return x + y;
        }

        float Sub(float x, float y)
        {
            return x - y;
        }

        float Mul(float x, float y)
        {
            return x*y;
        }
    }
-----Quat
Telastyn
Telastyn
Invoking a multicast delegate with return values returns the value of the last entry in the set (unless an exception of course).

Generally, if you want the return values of all, then a collection of delegates is more appropriate than the multicast.
Cryogenic
Cryogenic
Here's one way to reduce the result of a multicast delegate to one value :

class Program{    static void Main(string[] args)    {        Program p = new Program();        Func<float> f = p.Add;        Func<float> g = p.Sub;        Func<float> h = p.Mul;        Func<float> funcList = null;        funcList += f;        funcList += g;        funcList += h;        System.Console.WriteLine(ReduceMulticastDelegate(funcList, 2, 3, p.Add));    }    public delegate T Func<T>(T value1, T value2);    public static T ReduceMulticastDelegate<T>(Func<T> multicastDelegate, T val1, T val2, Func<T> reducer)    {        T result = default(T);        foreach (Func<T> singleCastDelegate in multicastDelegate.GetInvocationList())        {            result = reducer(result, singleCastDelegate(val1, val2));        }        return result;    }        float Add(float x, float y)    {        return x + y;    }    float Sub(float x, float y)    {        return x - y;    }    float Mul(float x, float y)    {        return x * y;    }}


Or if you're using C# 3.0 there's a more neat approach to doing this using lambda expressions and extension methods.

Edit:

or even better :
class Program{    static void Main(string[] args)    {        Program p = new Program();        Func<float> f = p.Add;        Func<float> g = p.Sub;        Func<float> h = p.Mul;        Func<float> funcList = null;        funcList += f;        funcList += g;        funcList += h;        funcList = ReduceMulticastDelegate(funcList, p.Add);        System.Console.WriteLine(funcList(2, 3));            }    public delegate T Func<T>(T value1, T value2);    public static Func<T> ReduceMulticastDelegate<T>(Func<T> multicastDelegate, Func<T> reducer)    {        return new Func<T>(delegate(T val1, T val2)        {            T result = default(T);            foreach (Func<T> singleCastDelegate in multicastDelegate.GetInvocationList())            {                result = reducer(result, singleCastDelegate(val1, val2));            }            return result;        });    }    float Add(float x, float y)    {        return x + y;    }    float Sub(float x, float y)    {        return x - y;    }    float Mul(float x, float y)    {        return x * y;    }}


Notice how the multicast delegat is called funcList(2,3);
Headkaze
Headkaze
Why not have a reference to a class as one of the parameters and place the return values into that.

For example when you have a KeyDown event in a form you can attach as many handlers as you want. The event has a KeyEventArgs parameter and inside that is a property called Handled. To say you have handled a KeyDown event for a key you simply set Handled to true.

private void textBox1_KeyDown(object sender, KeyEventArgs e){    if (e.KeyCode == Keys.Esc)        e.Handled = true;}

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.