I have a method with the following signature:
void MyMethod(Delegate d){};
void MyMethod(Expression exp){};
void MyMethod(object obj){};
However, this fails to compile:
MyMethod((int a) => a)
with the following error:
"Cannot convert lambda expression to type 'object' because it is not a delegate type"
Why doesn't this work?
Edit: I know that this works. The compiler compiles the lambda expression to a delgate in this case I think.
void MyMethod(Func<int, int> d){};
Kind regards,
Because the type System.Delegate isn't a "Delegate". It's just the base class. You have to use a delegate type with the correct signature. Define your Method as follows:
void MyMethod(Func<int, int> objFunc)
EDIT:
MyMethod(object) doesn't work because a lambda expression has no type at it's own, but the type is inferred from the type of the location it is assigned to. So object doesn't work either. You HAVE to use a delegate type with the correct signature.
void MyMethod(Action<int> lambdaHereLol)
{
lambdaHereLol(2);
}
in use:
var hurrDurr = 5;
MyMethod(x => Console.Write(x * hurrDurr));
C# is a statically typed language. The compiler needs to know the Type of everything it deals with. Lambdas are a bit hard to nail down, and sometimes the compiler can't figure it out. In my example above, if MyMethod took an object, the compiler couldn't figure out that x is an int (my example is simple, but there's nothing that says it can't be much more complex and harder to determine). So I have to be more explicit in defining the method that takes my lambda.
A lambda like (int a) => a will fit any delegate that takes an int and returns an int. Func<int,int> is just a single example, and you could easily declare one yourself with delegate int Foo(int x);. In fact this lambda expression will even fit a delegate that takes an int and returns a double, because the result of the lambda (a) is implicitly convertible to double.
In order for a lambda to be assignable to all the delegate types that it would fit, the lambda itself doesn't inherently have a type. Instead it takes on the type of the delegate you're using it as, as long as that's possible. ((int a) => a can't be assigned to Func<byte, byte> of course.)
While both Func<int, int> and the Foo delegate I defined can of course be converted to Delegate, a lambda can not be directly converted to Delegate because it is unclear what its actual signature would then be. After Delegate d = (int a) => a, would d be Foo, or Func<int, int>, or even Func<int, double>? All are valid possibilities, and the compiler has no idea what you intended. It could make a best guess, but C# is not the kind of language that does that kind of guesswork. This is also why you can't do something like var = (int a) => a.
I do think the error message that the compiler gives for Delegate d = (int a) => a; is very unclear:
Cannot convert lambda expression to type 'System.Delegate' because it is not a delegate type
Intuitively you would think Delegate is a delegate type, but that's not how things work. :)
Try this:
void MyMethod(Action<int> func) { }
You need to a strongly-typed delegate as a parameter to the method. The reason the other calls fail is because the C# compiler will not allow you to pass a lambda expression to a method expecting an Object because a lambda expression isn't necessarily always a delegate in all cases. This same rule applies for passing the lambda expression as a Delegate.
When you pass the lambda to a function like I have showed above, the compile can safely assume that you want the lambda expression to be converted to a specific delegate type and does so.
It's simply the nature of the compiler that you need to explicitly cast a delegate object to Delegate when passing it as a parameter of type Delegate. In fact, lambda expressions complicate things even further in that they are not implicitly convertable to delegates in this case.
What you require is a double cast, as such:
MyMethod((Delegate)(Func<int, int>)((int a) => a));
which of course corresponds to the method signature:
void MyMethod(Delegate d);
Depending on your situation, you may want to define a parameter of type Func<int> rather than Delegate (though I would hesitate adding an overload, just because it adds unnecessary complexity in honesty).
The reason this fails is the same reason an expression like "object del = (int a) => a" or even "var del = (int a) => a" fails. You might think that the compiler could figure out the type of your lambda expression since you explicitly give the type of the argument, but even knowing that the expression takes an int and returns an int, there are a number of delegate types it could be converted to. The Func delegate type is the one most used for generic functions such as this, but that is just a convention and nothing the compiler is aware of.
What you need to do is to cast the lambda expression to a concrete delegate type in order to have the compiler select the Delegate overload, either using the normal cast syntax (Func)((int a) => a), or using the delegate constructor syntax new Func((int a) => a).
Also, you normally do not want to use the untyped Delegate class unless you need to invoke something differently depending on the number of argument it accepts. It's almost always better to accept a Func or Action for things like callbacks.
Related
Given this code:
class C
{
C()
{
Test<string>(A); // fine
Test((string a) => {}); // fine
Test((Action<string>)A); // fine
Test(A); // type arguments cannot be inferred from usage!
}
static void Test<T>(Action<T> a) { }
void A(string _) { }
}
The compiler complains that Test(A) can't figure out T to be string.
This seems like a pretty easy case to me, and I swear I've relied far more complicated inference in other generic utility and extension functions I've written. What am I missing here?
Update 1: This is in the C# 4.0 compiler. I discovered the issue in VS2010 and the above sample is from a simplest-case repro I made in LINQPad 4.
Update 2: Added some more examples to the list of what works.
Test(A);
This fails because the only applicable method (Test<T>(Action<T>)) requires type inference, and the type inference algorithm requires that each each argument be of some type or be an anonymous function. (This fact is inferred from the specification of the type inference algorithm (§7.5.2)) The method group A is not of any type (even though it is convertable to an appropriate delegate type), and it is not an anonymous function.
Test<string>(A);
This succeeds, the difference being that type inference is not necessary to bind Test, and method group A is convertable to the required delegate parameter type void Action<string>(string).
Test((string a) => {});
This succeeds, the difference being that the type inference algorithm makes provision for anonymous functions in the first phase (§7.5.2.1). The parameter and return types of the anonymous function are known, so an explicit parameter type inference can be made, and a correspondense is thereby made between the types in the anonymous function (void ?(string)) and the type parameter in the delegate type of the Test method’s parameter (void Action<T>(T)). No algorithm is specified for method groups that would correspond to this algorithm for anonymous functions.
Test((Action<string>)A);
This succeeds, the difference being that the untyped method group parameter A is cast to a type, thereby allowing the type inference of Test to proceed normally with an expression of a particular type as the only argument to the method.
I can think of no reason in theory why overload resolution could not be attempted on the method group A. Then—if a single best binding is found—the method group could be given the same treatment as an anonymous function. This is especially true in cases like this where the method group contains exactly one candidate and it has no type parameters. But the reason it does not work in C#4 appears to be the fact that this feature was not designed and implemented. Given the complexity of this feature, the narowness of its application, and the existance of three easy work-arounds, I am not going to be holding my breath for it!
I think it's because it's a two-step inference:
It has to infer that you want to convert A to a generic delegate
It has to infer what the type of the delegate parameter should be
I'm not sure if this is the reason, but my hunch is that a two-step inference isn't necessarily easy for the compiler.
Edit:
Just a hunch, but something is telling me the first step is the problem. The compiler has to figure out to convert to a delegate with a different number of generic parameters, and so it can't infer the types of the parameters.
This looks like a vicious circle to me.
Test method expects a parameter of delegate type constructed from generic type Action<T>. You pass in a method group instead: Test(A). This means compiler has to convert your parameter to a delegate type (method group conversion).
But which delegate type? To know the delegate type we need to know T. We didn't specify it explicitly, so compiler has to infer it to figure out the delegate type.
To infer the type parameters of the method we need to know the types of the method arguments, in this case the delegate type. Compiler doesn't know the argument type and thus fails.
In all other cases either type of argument is apparent:
// delegate is created out of anonymous method,
// no method group conversion needed - compiler knows it's Action<string>
Test((string a) => {});
// type of argument is set explicitly
Test((Action<string>)A);
or type parameter is specified explicitly:
Test<string>(A); // compiler knows what type of delegate to convert A to
P.S. more on type inference
You're passing the name of the Method A. The .Net framework CAN convert it to an Action, but it's implicit and it will not take responsibility for it.
But still, a method name is NOT an explicit Action<> Object. And therefor it won't infer the type as an Action type.
I could be wrong, but I imagine the real reason C# cannot infer the type is due to method overloading and the ambiguity that arises. For example, suppose I have the following methods: void foo (int) and void foo (float). Now if I write var f = foo. Which foo should the compiler pick? Likewise, the same problem happens with your example using Test(foo).
SAMPLE CODE
int id = 123;
ThreadPool.QueueUserWorkItem(state => ThreadEntryPoint((int)state), id);
public void ThreadEntryPoint(int uniqueId)
{
Console.WriteLine("uniqueId=" + uniqueId);
}
QUESTION
From the provided LAMBDA expression, how does the compiler know that it needs to create an instance of QueueUserWorkItem(WaitCallback, Object)?
More specifically: I understand that it is inferring the delegate type. What I don't understand is what decision tree (from a high level) is it going through to select the correct delegate type to instantiate?
REFERENCES
ThreadPool.QueueUserWorkItem
ThreadPool.QueueUserWorkItem(WaitCallback, Object)
WaitCallback Delegate
QueueUserWorkItem(WaitCallback, Object)
QueueUserWorkItem(WaitCallback)
How does compiler infer the delegate type from LAMBDA expression?
Fundamentally, it doesn't.
The compiler infers the delegate type from the available overloads in the method group named QueueUserWorkItem. There are only two overloads, and only one with two parameters, and both overloads use the delegate type WaitCallback.
Thus, the delegate type has to be WaitCallback. With this determined, the compiler can then compile the lambda expression as an anonymous method and instantiate as the parameter to the QueueUserWorkItem() method call the necessary delegate object to call that anonymous method.
In a more complicated scenario, the compiler would have to perform some analysis to determine the "best" match for the overload, and that analysis may involve the lambda expression to the extent that it can eliminate overload possibilities based on the lambda expression.
But at no point does the compiler start with the lambda expression and go directly to the delegate type. For a lambda expression to be converted to a delegate instance, there needs to be some other context for the lambda expression that determines the needed delegate type, such as assignment to a typed variable, an explicit cast, or (as in this case) a method overload where the parameter the lambda expression is used for has a specific delegate type compatible with the lambda expression.
Note that there is still type inference for generic methods, in which the lambda is used to infer type parameters. Eric Lippert's comment explains this clearly:
There are some instances where the compiler must infer the constructed delegate type from the lambda. For example, if we have M<A, R>(Func<A, R> f) and M((string x) => x.Length) then the compiler will infer Func<string, something> first, from the lambda parameter, and then Func<string, int> from the body of the lambda.
My point here is that the compiler won't infer Func<T, TResult> from scratch. As Eric points out, the compiler does use the lambda to infer the type parameters, but the compiler still requires context in which the open generic type is known.
For more details, you should read the C# specification. It will detail how the overload resolution is performed and the rules that govern that and matching lambda expressions to types.
Additional reading:
.Net lambda expression— where did this parameter come from?
Why can't an anonymous method be assigned to var?
Why can't the compiler tell the better conversion target in this overload resolution case? (covariance)
Convert this delegate to an anonymous method or lambda
Not coincidentally, the first three include excellent discussions of the topic and related issues written by Eric Lippert, who used to work on the Visual Studio C# compiler and language design teams.
Suppose I had this in C#:
class OverloadTest
{
void Main()
{
CallWithDelegate(SomeOverloadedMethod);
}
delegate void SomeDelegateWithoutParameters();
delegate void SomeDelegateWithParameter(int n);
void CallWithDelegate(SomeDelegateWithoutParameters del) { }
void CallWithDelegate(SomeDelegateWithParameter del) { }
void SomeOverloadedMethod() { }
void SomeOverloadedMethod(int n) { }
}
Of course, this does not compile, because the line CallWithDelegate(SomeOverloadedMethod); is ambiguous.
Now, suppose there was only one CallWithDelegate(SomeDelegateWithoutParameter del) function (no overloads). In this case, there would be no ambiguity, because, from what seems to be happening, the compiler can look at the parameter type and discard SomeOverloadedMethod(int n) from the candidate list (since it can only take a SomeDelegateWithoutParameters), and so it compiles.
I don't intend to write code like this; this is just out of curiosity, from a compiler writer point-of-view. I couldn't find an answer about this, since it is quite confusing to put into words.
I'd like to know if there is any way in C# to disambiguate that call in Main() in the example given, so that it would compile. How can you specify it so that it resolves into CallWithDelegate(SomeDelegateWithoutParameters del) being passed SomeOverloadedMethod(), or CallWithDelegate(SomeDelegateWithParameter del) being passed SomeOverloadedMethod(int n)?
There are several ways to disambiguate overload resolution of method groups.
Method 1: cast the method group
CallWithDelegate((SomeDelegateWithoutParameters)SomeOverloadedMethod);
CallWithDelegate((SomeDelegateWithParameter)SomeOverloadedMethod);
This disambiguates the overload. That's pretty uncommon syntax in the wild, but it works (C# 5 spec §6.6 Method group conversions):
As with all other implicit and explicit conversions, the cast operator can be used to explicitly perform a method group conversion.
[...]
Method groups may influence overload resolution, and participate in type inference.
Method 2: instantiate the delegate explicitly
CallWithDelegate(new SomeDelegateWithoutParameters(SomeOverloadedMethod));
CallWithDelegate(new SomeDelegateWithParameter(SomeOverloadedMethod));
This is the same as the previous method without the syntactic sugar. See the spec at §7.6.10.5 Delegate creation expressions for more details.
The binding-time processing of a delegate-creation-expression of the form new D(E), where D is a delegate-type and E is an expression, consists of the following steps:
If E is a method group, the delegate creation expression is processed in the same way as a method group conversion (§6.6) from E to D.
[...]
There's even an example closely related to your question:
As described above, when a delegate is created from a method group, the formal parameter list and return type of the delegate determine which of the overloaded methods to select. In the example
delegate double DoubleFunc(double x);
class A
{
DoubleFunc f = new DoubleFunc(Square);
static float Square(float x) {
return x * x;
}
static double Square(double x) {
return x * x;
}
}
the A.f field is initialized with a delegate that refers to the second Square method because that method exactly matches the formal parameter list and return type of DoubleFunc. Had the second Square method not been present, a compile-time error would have occurred.
Method 3: use a lambda
CallWithDelegate(() => SomeOverloadedMethod());
CallWithDelegate(i => SomeOverloadedMethod(i));
CallWithDelegate((int i) => SomeOverloadedMethod(i)); // Explicit types, if needed
This form is not ambiguous but it has an indirection (the lambda is called, and it then calls the target method). This may get optimized by the JIT though, and it most probably won't have a visible performance impact anyway.
Method 4: use anonymous delegates
CallWithDelegate(delegate() { SomeOverloadedMethod(); });
CallWithDelegate(delegate(int i) { SomeOverloadedMethod(i); });
This is equivalent to the lambda calls, but it uses the bulkier (and older) delegate syntax.
If you'd like to know the exact overload resolution rules, they're described in the spec in §7.5.3 Overload resolution.
While i am no compiler expert, I can tell you that since you have supplied 2 overloaded methods that match both methods the compiler has no way of identifying your actual intention. It can't compile because at compile time there is currently no actual identifying information as now mentioned by Lucas you can cast to remove the ambiguity. For the compiler to solve this it would need run-time information of which method you actually wanted to use based on arguments that you may try and pass in.
Any way to avoid explicitly declaring MyMethodDelegate in a scenario like this?
bool MyMethod(string x)
{
//...
}
BeginInvoke(new MyMethodDelegate(MyMethod), x);
I know about lambdas a-la ()=>MyMethod(x), however I want to avoid them sometimes as they break edit-and-continue.
Edit: just BeginInvoke(MyMethod, x) does not work:
The best overloaded method match for 'System.Windows.Forms.Control.BeginInvoke(System.Delegate, params object[])' has some invalid arguments
Argument 1: cannot convert from 'method group' to 'System.Delegate'
Argument 2: cannot convert from 'string' to 'object[]'
BeginInvoke is defined as follows:
public IAsyncResult BeginInvoke(Delegate method, params object[] args);
It does not specify any specific delegate type, so the compiler cannot detect which delegate type to instantiate from BeginInvoke(MyMethod. x)
For framework >= 3.5 you can use predefined delegates Action<> and Func<> (in your case)
BeginInvoke(new Func<int, bool>(MyMethod), x);
Docs for Func
http://msdn.microsoft.com/ru-ru/library/bb549151.aspx
You can often use the simplified version
MyMethod
when a delegate is required. the keyword is often.
However if the compiler can't determine which type of delegate to convert the method group to you will have to help out with an explicit conversion
Lambdas can come in handy when you wish to pass a function that you haven't already defined and don't need at other locations in the code. Then Lambdas (and anonymous functions in general) will be very handy since you can then simply define the function at the spot where you need it.
in the case of BeginInvoke you are correct as noted in the comments that you can't you will need to explicitly convert the method group to a delegate either by casting or by assignment
Func<int,bool) m = MyMethod;
BeginInvoke(m,x);
BeginInvoke((Func<inte,bool>)MyMethod,x);
will compile or you can pass in a lambda because that's interpreted as a Func
BeginInvoke(a=>MyMethod(a),x);
Given this code:
class C
{
C()
{
Test<string>(A); // fine
Test((string a) => {}); // fine
Test((Action<string>)A); // fine
Test(A); // type arguments cannot be inferred from usage!
}
static void Test<T>(Action<T> a) { }
void A(string _) { }
}
The compiler complains that Test(A) can't figure out T to be string.
This seems like a pretty easy case to me, and I swear I've relied far more complicated inference in other generic utility and extension functions I've written. What am I missing here?
Update 1: This is in the C# 4.0 compiler. I discovered the issue in VS2010 and the above sample is from a simplest-case repro I made in LINQPad 4.
Update 2: Added some more examples to the list of what works.
Test(A);
This fails because the only applicable method (Test<T>(Action<T>)) requires type inference, and the type inference algorithm requires that each each argument be of some type or be an anonymous function. (This fact is inferred from the specification of the type inference algorithm (§7.5.2)) The method group A is not of any type (even though it is convertable to an appropriate delegate type), and it is not an anonymous function.
Test<string>(A);
This succeeds, the difference being that type inference is not necessary to bind Test, and method group A is convertable to the required delegate parameter type void Action<string>(string).
Test((string a) => {});
This succeeds, the difference being that the type inference algorithm makes provision for anonymous functions in the first phase (§7.5.2.1). The parameter and return types of the anonymous function are known, so an explicit parameter type inference can be made, and a correspondense is thereby made between the types in the anonymous function (void ?(string)) and the type parameter in the delegate type of the Test method’s parameter (void Action<T>(T)). No algorithm is specified for method groups that would correspond to this algorithm for anonymous functions.
Test((Action<string>)A);
This succeeds, the difference being that the untyped method group parameter A is cast to a type, thereby allowing the type inference of Test to proceed normally with an expression of a particular type as the only argument to the method.
I can think of no reason in theory why overload resolution could not be attempted on the method group A. Then—if a single best binding is found—the method group could be given the same treatment as an anonymous function. This is especially true in cases like this where the method group contains exactly one candidate and it has no type parameters. But the reason it does not work in C#4 appears to be the fact that this feature was not designed and implemented. Given the complexity of this feature, the narowness of its application, and the existance of three easy work-arounds, I am not going to be holding my breath for it!
I think it's because it's a two-step inference:
It has to infer that you want to convert A to a generic delegate
It has to infer what the type of the delegate parameter should be
I'm not sure if this is the reason, but my hunch is that a two-step inference isn't necessarily easy for the compiler.
Edit:
Just a hunch, but something is telling me the first step is the problem. The compiler has to figure out to convert to a delegate with a different number of generic parameters, and so it can't infer the types of the parameters.
This looks like a vicious circle to me.
Test method expects a parameter of delegate type constructed from generic type Action<T>. You pass in a method group instead: Test(A). This means compiler has to convert your parameter to a delegate type (method group conversion).
But which delegate type? To know the delegate type we need to know T. We didn't specify it explicitly, so compiler has to infer it to figure out the delegate type.
To infer the type parameters of the method we need to know the types of the method arguments, in this case the delegate type. Compiler doesn't know the argument type and thus fails.
In all other cases either type of argument is apparent:
// delegate is created out of anonymous method,
// no method group conversion needed - compiler knows it's Action<string>
Test((string a) => {});
// type of argument is set explicitly
Test((Action<string>)A);
or type parameter is specified explicitly:
Test<string>(A); // compiler knows what type of delegate to convert A to
P.S. more on type inference
You're passing the name of the Method A. The .Net framework CAN convert it to an Action, but it's implicit and it will not take responsibility for it.
But still, a method name is NOT an explicit Action<> Object. And therefor it won't infer the type as an Action type.
I could be wrong, but I imagine the real reason C# cannot infer the type is due to method overloading and the ambiguity that arises. For example, suppose I have the following methods: void foo (int) and void foo (float). Now if I write var f = foo. Which foo should the compiler pick? Likewise, the same problem happens with your example using Test(foo).