Can I ignore delegate parameters with lambda syntax? - c#

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");

Related

Can I define lambda default for some argument? [duplicate]

Is there a way to use optional arguments (default parameters) with lambda expressions in c#? I have read through the documentation but can find nothing to say one way or the other.
To illustrate, I can define simple method that uses an optional argument to supply a default value like so:
void MyMethod(string arg = "default-value")
{
Console.WriteLine(arg);
}
What I want to know is if I am able to do the same thing using a lambda expression.
// gives a syntax error
Action<string> MyMethod = (arg = "default") => Console.WriteLine(arg);
I can work in an optional parameter with a default value using a delegate, but this seems a bit clumsy.
delegate void MyDelegate(string arg = "default");
MyDelegate MyMethod = arg => Console.WriteLine(arg);
Alternatively I could check the parameter in the lambda body, something like...
Action<string> MyMethod = (arg) => Console.WriteLine(string.IsNullOrEmpty(arg) ?
"default" :
arg);
But again this seems a bit clumsy.
Is it possible to use optional parameters to set a default value in a lambda expression in c#?
No. The caller (the code invoking the delegate) doesn't "see" the lambda expression, so it doesn't make sense to specify the default parameter there. All the caller sees is the delegate. In your case, for example, the calling code only knows about Action<string> - how is the compiler meant to know to supply the default value that's specified by the lambda expression?
As an example of how things get tricky, imagine if this were viable. Then consider this code:
Action<string> action;
if (DateTime.Today.Day > 10)
{
action = (string arg = "boo") => Console.WriteLine(arg);
}
else
{
action = (string arg = "hiss") => Console.WriteLine(arg);
}
action(); // What would the compiler do here?
Bear in mind that the argument is provided by the compiler at the call site - so what should it do with the final line?
It's a bit like having an interface and an implementation - if you have a default parameter on an interface, that's fine; if you only have it on the implementation, then only callers who know the specific implementation will see it. In the case of lambda expressions, there's really no visible implementation for the caller to use: there's just the delegate signature.
The lambda will match whatever the signature of the delegate it's assigned to is; without being assigned to a delegate a lambda cannot compile.
If the delegate contains optional arguments then the use of that delegate can optionally supply arguments. If the delegate doesn't, then the use of that delegate cannot omit any arguments.
While the Action and Func delegates are very handy, and can represent most signatures, they can't represent any signature with optional arguments; you must use another delegate definition for that.
Remeber, Action and Func aren't particularly special, they're just two delegates that everyone uses so that they don't need to worry about creating their own for every little thing.

Define a lambda function and execute it immediately

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.

dynamic method invocation in expression tree

When constructing an expression tree, I have to use nodes invoking external methods in order to obtain values the expression could then continue evaluation with.
These methods are supplied as Func<T> and my code has no knowledge of where they originate from.
What is the most correct way of performing the mentioned invocation? I've tried something like this:
private Dictionary<string, Delegate> _externalSymbols;
private Expression _forExternalSymbol(string identifier)
{
Delegate method = _externalSymbols[identifier];
return Expression.Call(method.Method);
}
which works as long as the method fetched from the dictionary was created in compile-time. However, in case of Func<T> being a dynamic method obtained, for instance, by compiling another expression in runtime, this won't work out throwing
ArgumentException: Incorrect number of arguments supplied for call to method 'Int32 lambda_method(System.Runtime.CompilerServices.ExecutionScope)'
The desired effect may be achieved by wrapping the given function into one extra expression, but that seems quite hideous comparing to what it used to look like:
private Expression _forExternalSymbol(string identifier)
{
Delegate method = _externalSymbols[identifier];
Expression mediator = method is Func<double> ?
(Expression)(Expression<Func<double>>)(() => ((Func<double>)method)()) :
(Expression<Func<string>>)(() => ((Func<string>)method)());
return Expression.Invoke(mediator);
}
Also, this is hardly an extensible approach should I need to add support for types other than double and string.
I would like to know if there are better options which would work with dynamically created methods (preferably applicable to .NET 3.5).
which works as long as the method fetched from the dictionary was created in compile-time
No, it works as long as the method is static. For example, it also won't work if the delegate is a lambda that references something from its parent score (i.e. it's a closure).
The correct way to invoke a delegate is to use Expression.Invoke(). To get an Expression that represents your delegate, use Expression.Constant():
Expression.Invoke(Expression.Constant(method)))

What is the difference between Func<string,string> and delegate?

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.

What does SomeMethod(() => x.Something) mean in C#

(Note the code is an example)
I have the following syntax:
SomeMethod(() => x.Something)
What do the first brackets mean in the expression?
I'm also curious how you can get the property name from argument that is being passed in. Is this posssible?
What do the first brackets mean in the expression?
It's the lambda syntax for a method that takes no parameters. If it took 1 parameter, it'd be:
SomeMethod(x => x.Something);
If it took n + 1 arguments, then it'd be:
SomeMethod((x, y, ...) => x.Something);
I'm also curious how you can get the property name from argument that is being passed in. Is this possible?
If your SomeMethod takes an Expression<Func<T>>, then yes:
void SomeMethod<T>(Expression<Func<T>> e) {
MemberExpression op = (MemberExpression)e.Body;
Console.WriteLine(op.Member.Name);
}
The () is an empty argument list. You're defining an anonymous function that takes no arguments and returns x.Something.
Edit: It differs from x => x.Something in that the latter requires an argument and Something is called on that argument. With the former version x has to exist somewhere outside the function and Something is called on that outside x. With the latter version there does not have to be an outside x and even if there is, Something is still called on the argument to the function and nothing else.
It's a lambda expression. That is, it's a way to create an anonymous function or delegate.
The general form is:
(input parameters) => expression
If you have
() => expression
then you have created a function that takes no arguments, and returns the result of the expression.
C# uses type inference to figure out what the types of the values are, and it captures local variables (like your "x" variable) by means of a lexical closure.
I assume x is declared in somewhere inside your method, if yes, you can compare this lambda expression with a delegate that has no paramaters and return the type of x.someproperty
delegate{
return x.someproperty;
}
that is the same as:
() => x.someproperty
the () mean that this method doesn't take any parameters.
for example, if you assign a normal event handler using a lambda expression, it would look like this:
someButton.Click += (s, e) => DoSomething();
See also the following two blog posts that discuss exactly your second question and provide alternative approaches:
How to Find Out Variable or Parameter Name in C#?
How to Get Parameter Name and Argument Value From C# Lambda via IL? (Or "How NOT to Use .NET Linq Expressions in Order to Get Parameter Name and Argument Value From C# Lambda?")
To get the name of the property you need SomeMethod to have an argument of the type of System.Linq.Expressions.Expression<System.Func<object>>. You can then go through the expression to determine the property name.

Categories

Resources