At the page code.google.com/p/fakeiteasy/ I've noticed the line:
A.CallTo(() => shop.GetTopSellingCandy()).Returns(lollipop);
so the question is - how to pass a lambda expression as a method parameter ?
This function takes a parameter of type Func<T> (A normal delegate with a generic parameter), or, more likely, Expression<Func<T>> (an expression tree).
The function itself probably has a generic parameter which is inferred from the method passed.
By taking an expression tree, the function is able to inspect the code inside the expression and see what it does.
The code you've given is doing exactly that - passing a lambda expression as a paramter to a method call.
CallTo might have the signature 'CallTo(Action action)'. So lambda is passed as a delegate
Related
I have a Lazy<T> initialized with a lambda. How to see the body of the initializing lambda while debugging? I expect to have something like the DebugView of the Expression class but I've found nothing like that.
Because Lazy<T> takes a delegate, there is no Expression class involved. Your lambda is compiled like any other code in your project and there is no preview of that code during debug.
Lambda expression can be compiled either into IL or transformed into Expression Tree. Which one happens depends on the context. If your parameter is declared as delegate regular IL code will be generated. If it's Expression<TFunc> you'll get expression tree which can be previewed.
It's nicely explained on MSDN, based on Where method, which has two versions: Enumerable.Where which takes Func<T, bool> and Queryable.Where which takes Expression<Func<T, bool>>.
When you use method-based syntax to call the Where method in the
Enumerable class (as you do in LINQ to Objects and LINQ to XML) the
parameter is a delegate type System.Func<T, TResult>. A lambda
expression is the most convenient way to create that delegate. When
you call the same method in, for example, the System.Linq.Queryable
class (as you do in LINQ to SQL) then the parameter type is an
System.Linq.Expressions.Expression<Func> where Func is any of the Func
delegates with up to sixteen input parameters. Again, a lambda
expression is just a very concise way to construct that expression
tree. The lambdas allow the Where calls to look similar although in
fact the type of object created from the lambda is different.
Say I have a method with an input parameter named collectionSelector of type Func<TEntity, ICollection<TCollection>>.
I'd like to use this input parameter to load EF entities by using this method on an instance of DbContext:
context.Entry(entity).Collection(collectionExpression).Load()
The Collection method accepts a parameter of type Expression<Func<TEntity, ICollection<TElement>>>
I've searched around, but can't figure out how to initialize an Expression instance from an Func instance. Anyone an idea? Thanks in advance!
How about if you define your method to take an expression:
void Process(Expression<Func<TEntity,ICollection<TCollection>>> collectionSelector)
{
context.Entry(entity).Collection(collectionExpression).Load()
}
Now you can call it passing in a lambda:
Process(x=>x.GenerateCollection());
And the C# compiler will take care of converting the lambda to an expression for you.
I've searched around, but can't figure out how to initialize an Expression instance from an Func instance.
You can't. A Func is a delegate that points to a compiled method, there's no way to get an expression tree from that (well, maybe it's possible, but certainly not easily since you would need to decompile the method).
Depending on the context, a lambda expression can be compiled either to an anonymous method or to an expression tree. There is no conversion between the method and the expression...
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.
Based on my understanding , i interpret the meaning of Func delegate as follows.Please correct them as and when it is needed.
Declaration : Func<int> dg ;
1. Could i interpret it as "a Delegate
pointing to a method that returns an
integer?".
Declaration : Func<int,int> delg1=r=>2*r;
*2. Could i interpret it as " 'r' is a lambda expression that itself is a parameter of
an integer type being evaluated as '2 * r' and returns an int?
.*
Comparison : Delegate and lambda expression
3. if both Delegates and lambdas are working as function poiinters ,Where do there differ?.
Comparison : Are the following two declarations equal?
decl 1 : Func<int,int> fn=(r)=>45*r;
decl 2 : Expression<Func<int,int>> ex = (r) => r * 10;
4. if both of the above mentioned constructs are serving for the same purpose ,Where do there differ?.
1) Yes, but it would be more precise and accurate to say "a delegate referring to a method that takes no arguments and returns an integer".
2) No. "r" is not a lambda expression. "r" is used twice, first to declare a formal parameter of a lambda expression, and second as part of the body of that lambda expression. But "r" is not the lambda expression. The lambda expression is "r=>2*r"
3) Lambdas and delegates are different things. A lambda is the abstract notion of "a function that does some thing". A delegate type is the abstract notion of the type of things which are methods that take and return certain types. A particular delegate is a reference to such a method. A lambda is convertible to a compatible delegate type, and if you do so, at runtime, you get a delegate instance. But a lambda is convertible to other things as well, like an expression tree.
4) They do not serve the same purpose. The expression tree is an object which represents the computation mentioned in the lambda. The delegate is an object which actually performs the computation mentioned in the lambda.
Delegates and expressions are not the same thing. Delegates are strongly-typed references to methods while expressions are in-memory representations of code that can be treated as data. An expression can be compiled into IL (the Expression.Compile method) and this will give you a delegate to that newly compiled method.
Just remember that an expression can be turned into a delegate, but a delegate is just a delegate.
(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.