I can't directly pass a lambda
form.Invoke(() => AMethod(form));
Because oddly enough a lambda is not a delegate type (per the compiler error). I seem to recall different information in Jon Skeet's .NET 4.0 book. And on MSDN it says:
A lambda expression is an anonymous function that you can use to
create delegates or expression tree types
public static void Main()
{
Form form = new Form();
form.Show();
form.Invoke(() => AMethod(form));
Application.Run();
Console.Read();
}
public static void AMethod(Form form)
{
form.SendToBack();
}
}
Yet, here we receive a compiler error:
Cannot convert lambda expression to type 'System.Delegate' because it
is not a delegate type.
Lambda's are supposed to be syntactic sugar for anonymous delegates. So what is the story here? What have I missed?
Lambda's themselves are not delegates. But, like your quoted text, they can be used to create delegates:
form.Invoke(new Action(() => AMethod(form)));
Yes, lambdas are used to create delegates, but they are not themselves delegates. The primary issue here is that lambdas don't have a signature, their parameter list and return type are determined based on the context they are placed in. When you place a lambda somewhere where a particular defined delegate instance is expected then the compiler knows what signature the lambda must match to be valid.
Invoke on the other hand doesn't take some particular delegate type, it takes an instance of Delegate which doesn't have any signature. You need to wrap your lambda in new SomeActualDelegateType(...) (Action is a common choice for some delegate here, but not the only choice) to give it an actual signature.
Try to create Action: form.Invoke(new Action(() => MyMethod(form)));
Related
Just ran into this today
An anonymous function or method group cannot be used as a constituent
value of a dynamically bound operation.
when trying to do
static R ifNotNull<R>(dynamic o, Func<dynamic, R> returnFunc, R otherwise) {
return ReferenceEquals(null, o) ? otherwise : returnFunc(o);
}
and use it with
dynamic firstAddress = ...;
return ifNotNull<string>(firstAddress, (a) => a.address_1, null)
Now most of the limitations on dynamics make sense to me - you can't use an extension method because how is the compiler supposed to decide which static to compile it to? But I don't get this here. Where does the confusion come in? What exactly is the limitation?
What is the static type of the lamba a => a.address_1? You may be tempted to say it's a Func<dynamic, dynamic>. But remember:
A lambda expression is an anonymous function that you can use to
create delegates or expression tree types.
So maybe it's an Expression<Func<dynamic, dynamic>>. A lamda by itself doesn't have a single static type.
Now normally type inference would figure out that you're passing the lamba to a function that takes a Func and it will be converted to a delegate at compile time. However when you are calling with dynamic arguments the method call is dispatched dynamically.
If you have a method call with a dynamic argument, it is dispatched
dynamically, period. During the runtime binding, all the static types
of your arguments are known (emphasis mine), and types are picked for the dynamic
arguments based on their actual values.
So the fact that your method takes a Func isn't take into account, since the actual method call isn't determined until runtime so there is no type inference.
To get this to compile you'll have to cast your lamba to a Func<dynamic, string> as below:
return ifNotNull<string>(firstAddress, new Func<dynamic, string>((a) => a.address_1), null);
Now the static type of your lamda is known.
I meant that you need to cast the lambda method to the expect expression you want. Then it'll work just fine.
Like this:
return ifNotNull(firstAddress, (Func<dynamic, string>)((a) => a.address_1), null);
Control.BeginInvoke:
In both cases, it seems clear that the compiler has all the information it needs to infer the delegate type. Yet in neither case does the type inference seem to work:
BeginInvoke(myMethodThatTakesNoParams);
produces the compiler error
Error 105 The best overloaded method match for
'System.Windows.Forms.Control.BeginInvoke(System.Delegate)' has some
invalid arguments
as does
BeginInvoke(ShowProcessErrors, new object[] { process });
Both method calls only compile if I change them to explitly create a delegate and pass that. Both of the following compile fine:
BeginInvoke(new MethodInvoker(myMethodThatTakesNoParams));
and
BeginInvoke(new ProcessErrorDelegate(ShowProcessErrors), new object[] { process });
There doesn't seem to be any obvious reason why type inference won't work here. Is there a way to call BeginInvoke without explicitly creating a delegate?
The issue is that myMethodThatTakesNoParams isn't really a delegate but a so-called "method group" by the compiler. A method group isn't a real type in the CLR. It must be converted to delegate type to be used. When you use a method group like this:
Action a = myMethodThatTakesNoParams;
The compiler recognizes that you want to convert the method group to a delegate and inserts the conversion for you. It produces IL that effectively says:
Action a = new Action(myMethodThatTakesNoParams);
When you say:
Delegate d = myMethodThatTakesNoParams
The compiler doesn't really know what to do. It could theoretically pick any compatible delegate type for you, but C#, in general, does not insert types you did not use into expressions. Since it does not know what delegate you want the method group converted to, the compiler produces an error.
I used variable assignment in my examples, but the same logic applies for parameters to methods.
A work around would be to write your own extension method that has a specific delegate type in it:
static class ControlExtensions
{
public static IAsyncResult BeginInvoke(this Control c, Action a)
{
return c.BeginInvoke(a);
}
}
This usually comes as a surprise to .NET programmers, the C# Language Specific in section 15.1 explains:
Note that System.Delegate is not itself a delegate type; it is a class type from which all delegate types are derived
And of course there is no conversion of a method to a class. The first argument of BeginInvoke() must be a delegate type to keep the compiler happy. Maybe that sounds like an arbitrary limitation, it is most definitely not. A very important property of delegates is that they are type-safe. A pretty big deal in a statically typed language like C#. You can't invoke a delegate with too few arguments, or too many, or arguments of the wrong type. Checked when the delegate is created, you get a compile time error while you are still in your pajamas or the comfort of your cubicle. No surprises at runtime with your program suddenly keeling over at the most inopportune time of the day. This type checking of course cannot work for Delegate. So it is not a delegate type.
This does go wrong with Control.BeginInvoke(), it uses a back-door to get the method invoked. Kaboom when you pass Math.Pi instead of progress, you can't find out until you run the code. Not a pleasant exception either because it is unclear whether you got the BeginInvoke() call wrong or whether the invoked method threw an exception. Actually much more of a problem with Invoke().
Anyhoo, gotta give the compiler a delegate, more than one way to do that:
The venerable anonymous method syntax still works pretty well in this context:
this.BeginInvoke(delegate() { ShowProcessErrors(process); });
You already found MethodInvoker, I usually go for Action since it is shorter:
this.BeginInvoke(new Action(() => ShowProcessErrors(process)));
And you can of course always keep the compiler happy with an extension method:
this.BeginInvoke(() => ShowProcessErrors(process));
with:
static class Extensions {
public static void BeginInvoke(this Control ctl, Action a) {
ctl.BeginInvoke(a);
}
}
I'm defining a lambda and calling it, by appending "()", immediately.
Try:
int i = (() => 0) ();
Error:
Error CS0119: Expression denotes a anonymous method', where amethod group' was expected
Why is that?
You're not "defining a lambda".. you're wrapping parenthesis around what you think is one.
The compiler doesn't infer this type of thing. It needs context. You give it context by assigning or casting the representation of the lambda to a delegate type:
Func<int> f = () => 0;
int i = f();
Thats clear context. If you want an unclear one.. this sort of thing also works:
int i = ((Func<int>)(() => 0))();
A lambda just does not support being executed. A delegate supports being executed. A lambda expression can be implicitly converted to a delegate type. In case no such conversion is requested there is no "default" delegate type. Since .NET 2 we normally use Action and Func for everything but we could use different delegate types.
First convert to a delegate, then execute:
((Func<int>)(() => 0))()
One could argue that C# should default to using Action and Func if nothing else was requested. The language does not do that as of C# 5.
I see delegates in two forms:
A. Func<string, string> convertMethod = lambda
B. public delegate string convertMethod(string value);
I'm uncertain of what actually the difference between these two are. Are they both delegates? I believe the first one would use a lambda and the second would have to have a method to actually perform the work. I may be confused too.
First of all, your two examples are doing two totally separate things. The first is declaring a generic delegate variable and assigning a value to it, the second is just defining a delegate type. Your example, more completely, would be:
public static class Program
{
// you can define your own delegate for a nice meaningful name, but the
// generic delegates (Func, Action, Predicate) are all defined already
public delegate string ConvertedMethod(string value);
public static void Main()
{
// both work fine for taking methods, lambdas, etc.
Func<string, string> convertedMethod = s => s + ", Hello!";
ConvertedMethod convertedMethod2 = s => s + ", Hello!";
}
}
But more to the point, both Func<string,string> and delegate string convertMethod(string) would be capable of holding the same method definitions whether they be methods, anonymous methods, or lambda expressions.
As for which you should use, depends on the situation. If you want your delegate to be defined more by what it takes and returns, then the generic delegates are perfect. If you want the delegate to have some special name that gives more definition of what that delegate should do (beyond simple Action, Predicate, etc) then creating your own delegate is always an option.
The code sample you have is confusing things a bit so let me try and clear it up. The following 2 items are delegate declarations. These are easy to spot because they will always contain the delegate keyword
public delegate TReturn Func<TArg, TReturn>(Targ value);
public delegate string convertMethod(string value);
This line of code is assigning a value to a local which is typed to a delegate
Func<string, string> local = lambda;
The above code is not limited to using just lambdas though. The value could also be a compatible method group or another delegate value.
One other item to note is that even though Func<string, string> and convertMethod are both delegates with identical signatures their values are not convertible to each other. For example the following is illegal
Func<string, string> local1 = ...;
convertMethod local2 = local1; // Error!!!
From MSDN,
In versions of C# before 2.0, the only way to declare a delegate was
to use named methods. C# 2.0 introduced anonymous methods and in C#
3.0 and later, lambda expressions supersede anonymous methods as the
preferred way to write inline code.
and
There is one case in which an anonymous method provides functionality
not found in lambda expressions. Anonymous methods enable you to omit
the parameter list. This means that an anonymous method can be
converted to delegates with a variety of signatures.
You may also be interested in this SO answer on delegate keyword vs lambda expression.
Additionally, MSDN has a good article on Lambda Expressions:
delegate int del(int i);
static void Main(string[] args)
{
del myDelegate = x => x * x;
int j = myDelegate(5); //j = 25
}
In the previous example, notice that the delegate signature has one
implicitly-typed input parameter of type int, and returns an int. The
lambda expression can be converted to a delegate of that type because
it also has one input parameter (x) and a return value that the
compiler can implicitly convert to type int. (Type inference is
discussed in more detail in the following sections.) When the delegate
is invoked by using an input parameter of 5, it returns a result of
25.
A initializes an instance of a delegate (that can be called immediately). It's a variable of type Func< string, string >.
B specifies the definition of a delegate (its signature). It can be used to later define variables of type convertMethod.
I am curious why C# allows me to ignore delegate parameters in some cases but not others.
For instance this is permitted:
Action<int> action = delegate { Console.WriteLine("delegate"); };
but this is not:
Action<int> action = () => Console.WriteLine("lambda");
Is there a way to initialize a delegate and ignore the parameters using a lambda? I know that I can add a single parameter to the lambda and fix the previous line but this is more of an academic question pertaining to the compiler and why or how this works.
I believe that your first sample actually creates an anonymous function that is able to take on many different signatures whose body is the single statement Console.WriteLine.... Because it can match different signatures, it does not cause a problem. In the second sample, the lambda syntax itself defines a function that takes no parameters with the same body. Obviously the latter is not consistent with the defined Action so you get the error.
C# Anonymous Method Reference
There is one case in which an
anonymous method provides
functionality not found in lambda
expressions. Anonymous methods enable
you to omit the parameter list, and
this means that an anonymous method
can be converted to delegates with a
variety of signatures. This is not
possible with lambda expressions.
To elaborate on tvanfosson's answer; this behavior is described in the C# 3.0 language specification (§7.14):
The behavior of lambda-expressions and
anonymous-method-expressions is the
same except for the following points:
• anonymous-method-expressions permit
the parameter list to be omitted
entirely, yielding convertibility to
delegate types of any list of value
parameters.
• lambda-expressions permit parameter
types to be omitted and inferred
whereas anonymous-method-expressions
require parameter types to be
explicitly stated.
• The body of a lambda-expression can
be an expression or a statement block
whereas the body of an
anonymous-method-expression must be a
statement block.
• Since only lambda-expressions can
have an expression body, no
anonymous-method-expression can be
successfully converted to an
expression tree type (§4.6).
I think:
Action<int> action = () => Console.WriteLine("lambda");
is the equivalent of:
Action<int> action = delegate() { Console.WriteLine("delegate"); };
which wouldn't compile either. As Daniel Plaisted says () is explicitly saying there aren't any parameters.
If there were an equivalent of delegate{} it might be:
Action<int> action = => Console.WriteLine("lambda")
Which isn't very pretty and I suspect it suspect isn't in the spirit of lambda expressions.
As others said, no, you can't skip declaring the parameters to a lambda. But, for cleanliness, I suggest giving them a name such as _. For example
foo.Click += (_,__) => { ... }
You aren't ignoring them per-se, but you're indicating you don't care what they are and will not use them.
The () => ... syntax explicitly specifies that the lambda takes no parameters. Perhaps the language could be modified so that () => really meant "Infer the parameters of this lambda for me" in the same way the delegate syntax does, but that would make the language more complicated. When designing new language features, you start at minus 100, and I don't think this one passes the test.
There may also be more technical reasons why this would be difficult to implement (which is probably more in line with what you were asking for, but I doubt the technical reasons drove this decision if it ever came up).
I'd say it's to have a forced use of the parameters of the lambda expression.
Take your first example, how would you interact with the passed in value, there's no local representation of it.
What about this?
Func<int> lamdapointer = () => TwoArgMethodThatReturnsInt(10,20); // the same method cannot be called with the delegate "NoArgmethodThatReturnsInt"
lamdapointer();
Delegate int NoArgmethodThatReturnsInt();
NoArgmethodThatReturnsInt del = NoArgmethodThatReturnsInt; // only this is possible with delegates
public int TwoArgMethodThatReturnsInt(int x,int y)
{
return x + y;
}
public int NoArgmethodThatReturnsInt()
{
return 20;
}
Actually, delegate {} does not specify any parameters and fits any delegate method signature - therefore it is permitted in your first construcion.
The Lambda expression () => ...; specifically states parameterless delegate, which contradicts the signature required by Action - a delegate with single parameter.
You may want to use one of the following options.
If you need the action to have a parameter, you can do it the next way ("_" is a legal character for identifier name).
Action<int> action = _ => Console.WriteLine("lambda");
Or you may want to use parameterless Action as follows:
Action action = () => Console.WriteLine("lambda");