9232

Can’t assign to delegate an anonymous method with less specific parameter type

Question:

I’m able to assign a method M to delegate object d with a less specific parameter type, but when I want to assign an anonymous method with same the signature as method M to d, I get an error.

Why is that?

class derivedEventArgs : EventArgs { } delegate void newDelegate(object o, derivedEventArgs e); static void Main(string[] args) { newDelegate d = M; // ok d = (object o, EventArgs e) => { }; // error } public static void M(object o, EventArgs e) { }

Answer1:

Jared is of course correct that this is by design.

The reason for that design is that in the contravariant method conversion case, you might have a method that you didn't write, and be assigning it to a delegate variable that you didn't write either. You don't control the types. So we go a bit easy on you and let the parameters match contravariantly and the return types match covariantly.

In the lambda-to-delegate conversion, you <em>do</em> control the thing being assigned. There is nothing <em>stopping</em> you from making it an exact match in the parameter types and therefore we <em>require</em> you to. No fudging allowed here.

Answer2:

This is covered in section 6.5 of the C# language specification. If you explicitly type the parameters of an anonymous function, they must match in both type and modifiers in order to be compatible signatures.

<blockquote>

Specifically, a delegate type D is compatible with an anonymous function F provided

...

If F has an explicitly typed parameter list, each parameter in D has the same type and modifiers as the corresponding parameter in F.

</blockquote>

Answer3:

While you have got your answer, I will provide a workaround if this is <em>required</em>. Say, all you got is a delegate of signature (object, EventArgs) in which case you want to convert it to your newDelegate type, you could do:

SomeDelegate p = (object o, EventArgs e) => { }; //comes from somewhere NewDelegate d = (o, e) => p(o, e); //can rewrite like this

Alternately with generics and (contra) variance feature of generic delegates, you can do it with one delegate type:

delegate void NewDelegate<in T>(object o, T e) where T : EventArgs; //then NewDelegate<EventArgs> p = (object o, EventArgs e) => { }; //comes from somewhere NewDelegate<DerivedEventArgs> d = p; //straightforward assignable - contravariance

Recommend

  • What is the variance of argument types in Scala?
  • Why are LSP violations in PHP sometimes fatal, and sometimes warnings?
  • Easiest way to find IsManager in SQL
  • Ember Handlebars Iterate object and display key inside nested each helper
  • Understanding scala's _ vs Any/Nothing
  • Type L is in contravariant position in type A => Either[L, B]
  • Can’t assign to delegate an anonymous method with less specific parameter type
  • How to reset the selected index dropdown value in html?
  • Resizing ToolStripButtons to fit complete BackGround image
  • Delphi: Form becomes Frozen while assigning strings in thread
  • javascript variables, What does var x = a = {} do?
  • RavenDB indexing errors
  • how to solve invalid conversion specifier warning in iphone app
  • abstracting over a collection
  • SAXReader not re-ecape characters
  • Web.config system.webserver errors
  • Email format validation in mvc3 view
  • C# - Is there a limit to the size of an httpWebRequest stream?
  • How to add date and time under each post in guestbook in google app engine
  • Controls, properties, events and timers running in design time
  • Arrow is showed instead of the material design version hamburger icon. Why doesn't syncState in
  • How to make Safari send if-modified-since header?
  • Weird JavaScript statement, what does it mean?
  • How do you troubleshoot character encoding problems?
  • Function pointer “assignment from incompatible pointer type” only when using vararg ellipsis
  • 0x202A in filename: Why?
  • How to pass list parameters for each object using Spring MVC?
  • How to format a variable of double type
  • coudnt use logback because of log4j
  • Setting background image for body element in xhtml (for different monitors and resolutions)
  • File not found error Google Drive API
  • JaxB to read class hierarchy
  • How to Embed XSL into XML