In C# all delegate types are incompatible with one another, even if they have the same signature. As an example:
delegate void D1();
delegate void D2();
D1 d1
Basically because the compiler makes two classes for you. The same reason you can't do:
class A {}
class B {}
void Main()
{
A a = new A();
B b = a;
}
For example, the following code
void Main() {}
delegate void D();
class C {}
The IL code is:
D.Invoke:
D.BeginInvoke:
D.EndInvoke:
D..ctor:
C..ctor:
IL_0000: ldarg.0
IL_0001: call System.Object..ctor
IL_0006: ret
In C# all delegate types are incompatible with one another, even if they have the same signature. What is the reasoning behind this behaviour and language design decision?
First off, I think that it is fair to say that many of the runtime and language designers regret this decision. Structural typing on delegates -- that is, matching by signature -- is a frequently requested feature and it just seems strange that Func<int, bool>
and Predicate<int>
can't be freely assigned to each other.
The reasoning behind the decision as I understand it -- and I hasten to add that this decision was made about six years before I started on the C# team -- is that the expectation was that there would be delegate types with semantics. You want this to be a type error:
AnyFunction<int, int> af = x=> { Console.WriteLine(x); return x + y; };
PureFunction<int, int> pf = af;
A "pure" function is a function which produces and consumes no side effects, consumes no information outside of its arguments, and returns a consistent value when given the same arguments. Clearly af
fails at least two of those, and so should not be assignable to pf
as an implicit conversion.
But semantics-laden delegate types never happened, so it's a bit of a misfeature now.
Delegate is nothing but just another type. They are incompatible for the same reason class A {}
and class B {}
would be incompatible.
delegate void D1();
Will approximately compile to something like:
class D1 : MulticastDelegate { .... }