C # Delegate in question hood

I was doing some changes in the variance of delegates after reading the next question on SO: Delegate.CreateDelegate () and generics: binding to binding to target method

I found a very good code from Barry kelly at https://www.blogger.com/comment.g?blogID=8184237816669520763&postID=2109708553230166434

Here it is (in a protracted form :-)

using System;

namespace ConsoleApplication4
{
    internal class Base
    {
    }

    internal class Derived : Base
    {
    }

    internal delegate void baseClassDelegate(Base b);

    internal delegate void derivedClassDelegate(Derived d);


    internal class App
    {
        private static void Foo1(Base b)
        {
            Console.WriteLine("Foo 1");
        }

        private static void Foo2(Derived b)
        {
            Console.WriteLine("Foo 2");
        }

        private static T CastDelegate<T>(Delegate src)
            where T : class
        {
            return (T) (object) Delegate.CreateDelegate(
                                    typeof (T),
                                    src.Target,
                                    src.Method,
                                    true); // throw on fail
        }

        private static void Main()
        {
            baseClassDelegate a = Foo1; // works fine

            derivedClassDelegate b = Foo2; // works fine

            b = a.Invoke; // the easy way to assign delegate using variance, adds layer of indirection though

            b(new Derived());

            b = CastDelegate<derivedClassDelegate>(a); // the hard way, avoids indirection

            b(new Derived());
        }
    }
}

      

I understand all of this except this one (which looks very simple).

b = a.Invoke; // easy way to assign a delegate using variance, adds a layer of indirection though

Can anyone tell me:

  • how can the call be called without passing the parameter required by the static function.
  • When happens under the hood when you assign the return value from the invoke call
  • What does Barry mean by further direction (in his commentary)
+2


a source to share


1 answer


It does not call Invoke

(note the absence ()

), it uses implicit delegate creation to set b

equal to the new instance derivedClassDelegate

that points to the method Invoke

a

. An additional indirection is that when called, b

it invokes a.Invoke(new Derived())

, not just a(new Derived())

.

To make what's actually happening more explicit:

baseClassDelegate a = Foo1; // works fine 

derivedClassDelegate b = Foo2; // works fine 

b = new derivedClassDelegate(a.Invoke); // the easy way to assign delegate using variance, adds layer of indirection though 

b(new Derived());

b = CastDelegate<derivedClassDelegate>(a); // the hard way, avoids indirection 

b(new Derived());

      

The first call b

leads to a chain like this (parameters removed for simplicity):

b() -> a.Invoke() -> Foo1()

      



The second call b

results in the following:

b() -> Foo1()

      

but

This is only necessary if you need a delegate from one signature to invoke a delegate from another (less strong) signature. In his example, you can just install b = Foo1

and it will compile, but that would not illustrate the point.

+9


a source







All Articles