2

I was reading Jon Skeet's answer here

and one of his samples was :

  static void Main()
    {
        int x = 0;
        Foo( delegate { return x; } );
    }

    static void Foo(Func<int, int> action)
    {
        Console.WriteLine("I suspect the anonymous method...");
    }

But how Foo(Func<int, int>) can deal with delegate { return x; } which is Func<int> ?

As a matter of fact also Func< int,int,int,int,...> can deal with delegate { return x; } ...

question 1 Any explanation for this behavior please ?

question 2

I have this code :

class MyClass
{
    public delegate void MyEventHandler(object sender);
    public  event MyEventHandler MyEvent;
}

and I wanted to use generic handlers so :

class MyClass
{
    public  Action<object> MyEventHandler;
    public  event MyEventHandler MyEvent;
}

but I get this error :

'UserQuery.MyClass.MyEventHandler(object)' is a 'method' but is used like a 'type'

Why isn't it recognizing it ?

Community
  • 1
  • 1
Royi Namir
  • 144,742
  • 138
  • 468
  • 792
  • Try calling it with `() => x` instead then compare with `(Func)(delegate { return 1; })`; there be magic with delegates. –  Nov 10 '12 at 20:50
  • `Func`is the same as `delegate { return 1; }` ? – Royi Namir Nov 10 '12 at 20:53
  • As for the 2nd question (please keep questions separate!) a *field* is not a *delegate declaration* (although perhaps there is a better term for this) –  Nov 10 '12 at 20:53

1 Answers1

8

The answer to your first question is that the arguments to the delegate are inferred by the compiler. An anonymous method is compiled that takes an int as an argument, and does nothing at all with it. The code could have been written like this:

Foo( delegate (int dummy) { return x; } );

By omitting the parameter list, you are telling the compiler to emit a method that has the same argument types as the delegate type in the current context. The compiler knows that a Func<int, int> is expected, so it is able to make the anonymous method's argument types match.

In other words, delegate { ... } tells the compiler "create an anonymous method, but I don't care what the arguments are because I'm not going to use them, so emit whatever arguments will allow this delegate to be acceptable in this context." (This is different from delegate () { ... } which means "create an anonymous method that takes zero arguments." Note the parentheses. If you add these parentheses to your example code, it will indeed fail to compile.)

In the second case, you are using a field name where a type name is expected. Defining a field does not create a type with the field's name. Your first example is correct; in that case, MyEventHandler is a type and not a field. (Even if that did work, using generics would not really be helpful, since the final delegate signature is already determined at compile time. You would get no net advantage from using generics.)

cdhowie
  • 158,093
  • 24
  • 286
  • 300
  • So all i need is `class MyClass { public event Action MyEvent; }` right ? – Royi Namir Nov 10 '12 at 21:05
  • 1
    Yes, that would work. However, I would suggest using the `EventHandler` delegate type instead of `Action`. – cdhowie Nov 10 '12 at 21:07
  • Note that `Action` is **contravariant** in `T`. According to [this post](http://blogs.msdn.com/b/cburrows/archive/2010/03/30/events-get-a-little-overhaul-in-c-4-afterward-effective-events.aspx) you should not use a contravariant delegate type for an event. – Jeppe Stig Nielsen Nov 11 '12 at 00:51