A problem with reverse type inference in C#
Anonymous methods and lambda expressions, language features of C# introduced in versions 2.0 and 3.0, have the interesting quality that they infer their type from their context. In other words, rather than determining the type of the expression from operator(s) of the expression, this particular kind of selector is given its type based on the assignment/argument it fulfills.
delegate void D(x : integer);D d = delegate { ... }; // the type of the anonymous method becomes D
This is of course the reverse of the usual type inference direction. To illustrate the strangeness of this concept, imagine that this kind of thing worked with other types:
int[] x = new [] { 1, 2, 3 }; // right array selector "becomes" of type int[]
This seems harmless enough. I've been observing this odd reverse type inference with interest, wondering whether it is a good thing or not. I must say there were a few times when we considered similar such things in D4.
Today, however, this "feature" bit me and I think I see now why it is probably never a good idea. Here is a simplified illustration of the situation:
delegate int D();
D d = delegate { return 1.0; };
What do you suppose the error will be for this obvious type mix up? Answer: "Cannot convert from 'anonymous method' to 'D'". Doing the following, however, results in the expected "Cannot implicitly convert type 'decimal' to 'int'" error:
D d = (D)delegate { return 1.0; };
In a more complicated situation, one is left scratching one's head wondering if everything learned about delegates was a lie. It seems that trying to reverse the direction if type inference could lead to all sorts of similar chicken-or-egg conundrums. It seems that a more elegant solution would have been to provide some form of implicit conversion.
My take-aways are thus:
1. If I ever see a similar delegate conversion error, my first action will be to cast the anonymous delegate to what I expect it to be so that I may see the "real" error.
2. Treat all temptations to do reverse type inference with much suspicion.