(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.
Related
I have this line of code, it works but I don't understand it:
Genres.Find(delegate (Genre genre) { return genre.Id == id; });
Genres is a list of genre(music)
What exactly is happening here?
C# provides two ways of defining delegates without writing a named method for it - the old anonymous method syntax introduced in C# 2.0, and the shorter lambda syntax introduced in C# 3.0.
Your code is the old way of writing this:
Genres.Find(genre => genre.Id == id);
This article describes the evolution of anonymous functions in C#.
Your Find method takes a predicate delegate. Depending on the version of .NET targeted by your code it may or may not be the System.Predicate<T> delegate, but its functionality is equivalent. An anonymous method in parentheses provides an implementation of your predicate, allowing you to pass arbitrary conditions to your Find(...) method.
It says, find the Genre (from the list Genres) which has the Id equal to the value from the variable id.
The keyword delegate says, that this is a kind of inline function which decides whether the check is true for each item or not. The beginning (Genre genre) says "given I would call each element genre in the loop, I can check each items' Id with its named variable Id". This is: genre.Id == id.
A modern approach would be the usage of lambdas like:
var x = Genres.Find(g => g.Id == id);
In this case g is your loop variable you can check against.
An intuitive way to see it:
Genres.Find( --- The CompareGenres function is being called from here --- );
bool CompareGenres(Genre genre)
{
return genre.Id == id;
}
Find accepts a Predicate < T >, T is the type of the parameter, in this case: you're passing an instance of Genre which is being supplied by the Find method.
"The Predicate is a delegate to a method that returns true if the object passed to it matches the conditions defined in the delegate."
So you're just passing a method as a parameter in the form of a delegate
Maybe I do not use the right terms here. But form an abstract point of view: The Find method here accepts a delegate as parameter. It allows you to implement the "find" algorithm (here comparing the id). It is flexible code you could also compare any other object of "genre".
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'm trying do the next instruction in c#:
Form form = this.MdiChildren.FirstOrDefault(x => x is Type.GetType("MyFormName"));
But i have a error: Method name expected.
What would be the correct usage of the instruction.
Since you have a Type instance you need to use IsAssignableFrom instead of is:
x => Type.GetType("MyFormName").IsAssignableFrom(x.GetType())
This of course assumes that you really can't reference the actual type at compile time. If you can, then you could instead simplify this code to:
.OfType<MyFormName>().FirstOrDefault();
Which is going to have something internally that resembles:
x is MyFormName
Which is how the is operator is designed to be used.
I have a method with the following signature:
private PropertyInfo getPropertyForDBField(string dbField, out string prettyName)
In it, I find the associated value prettyName based on the given dbField. I then want to find all properties, if any, that have the name prettyName, so I'm trying to do the following:
IEnumerable<PropertyInfo> matchingProperties =
getLocalProperties().Where(prop =>
prop.Name.Equals(prettyName)
);
However, this gives the following error:
Cannot use ref or out parameter 'prettyName' inside an anonymous method, lambda expression, or query expression
By the point in the method where I'm trying to use prettyName in the Where lambda parameter, prettyName is definitely initialized. I return if prettyName cannot be initialized to a valid value. Is there some trick I could do here to let me use prettyName in the lambda expression?
Edit: I'm using .NET 3.5 if it matters.
Just to clarify. It's possible to use ref/out arguments from a called method in a lambda.
You can also use a ref or out if you specify type of the parameter. Which means sending prettyName as a parameter to the lambda.
(prop, ref string prettyName) => prop.Name.Equals(prettyName);
Where clause takes in only one argument, which is the property element in the list. This is what prevents you from adding an argument to the lambda.
Didn't want to leave people the false impression that you cannot use these arguments in a lambda. You just can't use them by capture.
As the compiler error indicates, it isn't allowed to use out or ref parameters inside lambda expressions.
Why not just use a copy? It's not like the lambda wants to mutate the variable anyway, so I don't see a downside.
string prettyNameCopy = prettyName;
var matchingProperties = getLocalProperties()
.Where(prop => prop.Name == prettyNameCopy);
Alternatively, you can use a local throughout (to evaluate the appropriate name etc.), and assign the outparameter prettyName just before returning from the method. This will probably be more readable if there isn't significant branching within the method.
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");