lambda expression syntax vs LambdaExpression class - c#

This line of code that tries to assign a lambda expression to a LambaExpression typed variable,
LambdaExpression expr = n => n;
it fails with compile error message:
Cannot convert lambda
expression to type
'System.Linq.Expressions.LambdaExpression'
because it is not a delegate
type
So it needs to be a delegate type. Conceptually it seems odd to me because I can build out a LambdaExpression instance using a factory method like so.
Factory Lambda from MSDN
LambdaExpression lambdaExpr = Expression.Lambda(
Expression.Add(
paramExpr,
Expression.Constant(1)
),
new List<ParameterExpression>() { paramExpr }
);
and that's not a delegate type.
It makes we wonder why lambda to LambaExpression cannot work?

Well, this does work:
Expression<Func<int, int>> exp = n => n;
LambdaExpression lambda = exp;
Note that Expression<TDelegate> derives from LambdaExpression.
I think the reason you can't just use LambdaExpression as the type is that then the type of n (in your example) could not be inferred.
Consider the fact that you also can't do this, for basically the same reason:
// What is this? An Action? A ThreadStart? What?
Delegate d = () => Console.WriteLine("Hi!");
Whereas you can do this:
Action a = () => Console.WriteLine("Hi!");
Delegate d = a;
It's essentially the same thing.

Because LambdaExpression is a way to generate lambda expressions at runtime, where as n => n gets converted to a generated class at compile time.
In short: they are two different things to do the same thing, but can't be used together.

To quote MSDN
The LambdaExpression type represents a lambda expression in the form of an expression tree. The Expression type, which derives from LambdaExpression and captures the type of the lambda expression more explicitly, can also be used to represent a lambda expression. At runtime, an expression tree node that represents a lambda expression is always of type Expression.
The value of the NodeType property of a LambdaExpression is Lambda.
Use the Lambda factory methods to create a LambdaExpression object.

Read carefully what errror message is saying. LambdaExpression is not a delegate. It is normal class. Read http://msdn.microsoft.com/en-us/library/system.linq.expressions.lambdaexpression.aspx. Because it has Lambda in name doesn't mean it is same as 'true' lambda.

Related

How does linq Expression<TDelegate> assignment work on a language syntax level

TLDR: How does this compile?
class A{};
Expression<Func<A, int>> e = x => 24; // I don't understant what makes this compile
// and what happens at this assignment
What is the minimum class E to be able to compile E e = x => 24;
Some investigation
class E {};
E e = x => 24;
Visual Studio error is "Cannot convert lambda expression to type 'E' because it is not a delegate type" which is confusing because as far as I know a delegate is declared like this:
int delegate MyHandle();
and I didn't find any way of making a class a delegate.
Furthermore I have looked at the metadata of Expression -> LambdaExpression -> Expression<TDelegate> and wasn't able to identify what syntax/declaration makes Expression<TDelegate> act like a delegate.
Even more I have tried to create my own class E to mimic Expression<TDelegate> and I wasn't even able to compile the class
// basically a copy-paste of the metadata of `Expression<TDelegate>`
public sealed class E<TDelegate> : LambdaExpression
{
public TDelegate Compile() => default(TDelegate);
public TDelegate Compile(DebugInfoGenerator debugInfoGenerator) => default(TDelegate);
public TDelegate Compile(bool preferInterpretation) => default(TDelegate);
public Expression Update(Expression body, IEnumerable<ParameterExpression> parameters)
=> default(Expression);
protected override Expression Accept(ExpressionVisitor visitor) => null;
}
getting the error "'LambdaExpression' does not contain a constructor that takes 0 arguments"
Context (can be skipped):
I am getting started with Moq and because I just cannot take things for granted I am trying to understand how it works / how it is implemented. So this the first part of a series of inquiries about that.
I am now specifically trying to understand
public class A
{
public virtual int Foo() => throw new NotImplementedException();
public virtual int Bar() => throw new NotImplementedException();
}
var a = new Mock<A>();
a.Setup(x => x.Foo()).Returns(24); // ??
Console.WriteLine(a.Object.Foo());
I am trying to understand how the information "the method Foo" is passed to a
by passing that lambda? As far as I know a lambda is just a callable object, but somehow magically a knows the actual body of the lambda, i.e. will throw if you pass x => 24 or x => x.Foo() + x.Bar() but will accept x => x.Foo()
And I see that Setup parameter is of type Expression<Func<A, int>> hence my current question.
The C# specification gives special treatment to System.Linq.Expressions.Expression<D>; you cannot get the same treatment for your own type.
Expression trees permit lambda expressions to be represented as data structures instead of executable code. Expression trees are values of expression tree types of the form System.Linq.Expressions.Expression<D>, where D is any delegate type.
Source: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/types#expression-tree-types
This is a Lambda expression:
x => 24
According to MSDN Lambda expressions a lambda expression can be used to create a delegate or an expression tree type.
A Func<T, int> is a delegate function that takes a T as input and returns an int as output. If you assign the lambda expression above to this Func, then the compiler assumes that the x in the lambda expression is the input of the Func, and the part after the => is the output of the Func:
Func<string, int> func = x => x.Length;
Here x is expected to be a string, the part after the => may use, but is not obliged to use, this x to produce the output which has to be an int.
Func<int, int> func = x => x = -x;
Here x is expected to be an int. The return of the function is -x which is also an int.
Expression is the base class of all kinds of expressions. Expressions represent an operation that return a value. The most basic expressions are constants, they represent just a constant value, like 24. Other expressions might be additions, which take as input two expressions and have one output value. Other expressions are multiplication, negation, etc, which return a "number", or boolean expressions like AND OR NOR etc which return a Boolean.
A special kind of expression (so a derived class) is a LambdaExpression. A LambdaExpression usually represents a function-like object: it has zero or more input parameters and one output parameter. You assign a value to a LambdaExpression using a lambda expression (note the space in lambda expression!):
Expression<Func<string, int>> myExpression = x => x.Length;
I wrote earlier what the lambda expression x => x.Length does. the statement above creates an object of type System.Linq.Expressions.Expression<TDelegate>, which is of type LambdaExpression, hence you can assign it to an Expression<Func<string, int>>.
Your question:
What is the minimum class E to be able to compile E e = x => 24?
Your class E will need a constructor (or assignment operator) that accepts a System.Linq.Expressions.Expression<Func<MyClass, int> as parameter. If you don't use the x from your lambda expression MyClass can be object
Of course it is also accepted if the constructor takes any of the base classes, like Expression. However, if you do so you won't be able to used any of the Expression<Func<MyClass, int> functionality.
About your Mock code
Apparently you have a class A with two functions Foo and Bar, and you want to instantiate a Mock object to mock the functionality of A.
var myAmock = new Mock<A>();
myAmock.Setup(x => x.Foo()).Returns(24);
This says, that myAmock is an object that should mock behaviour of class A. Whenever someone calls the Foo function it should return a value of 24.

Extending member-access expression

I have an expression of type Expression<Func<TOwner, object>> that was created using lambda (syntax). It has member-access expression somewhere in the body. I would like to create expression that selects another property of the mentioned expression's result.
I terms of C# it should look like this:
Expression<Func<MyClient, object>> exStartingPath = x => x.Address;
Expression<Func<MyClient, object>> exExtendedPath = ExtendSelection(exStartingPath, "Street");
//exExtendedPath should be equivalent to x => x.Address.Street
How should ExtendSelection(...) be implemented? Should I decompose already existing expression and compose new one using some traversing technique or is there any API that can just 'append' member selection?
Just grab the body of the lambda, apply the member access to that, and then wrap the whole thing back up into a new lambda.
public static Expression<Func<TSource, TTarget>> ExtendSelection<TSource, TTarget>(
Expression<Func<TSource, TTarget>> expression, string member)
{
var body = Expression.PropertyOrField(expression.Body, member);
return Expression.Lambda<Func<TSource, TTarget>>(body, expression.Parameters);
}

Rewrite Lambda expression with System.Linq.Expressions APIs

I am stuck on this for hours. All I want to do is build an Expression tree by rewriting this following expression using Expression class APIs:
var Expression<Func<T, bool>> expr = x => x.SomeProperty == value;
What I got so far are:
{
var param = Expression.Parameter(typeof(T), "x");
var lhs = Expression.Property(param, "SomeProperty");
var rhs = Expression.Constant(value, value.GetType());
return Expression.Call(typeof(object).GetMethod("Equals", BindingFlags.Static | BindingFlags.Public), lhs, rhs);
}
This works fine if T is a primitive type or enumeration. But I got an exception if T is a reference type, a class etc.
Exception Message:
Unable to create a constant value of type 'TypeName'. Only primitive
types or enumeration types are supported in this context.
Thanks in advance.
You don't need to specify the type explicitly, in this case, as long as the value is not null (which I'm assuming it isn't, as you're calling GetType() on it).
This should do it.
var param = Expression.Parameter(typeof(T), "x");
var property = Expression.Property(param, "SomeProperty");
var compareValue = Expression.Constant(value);
var equals = Expression.Equal(property, compareValue);
return Expression.Lambda<Func<T, bool>>(equals, param);
The expression generated was passed to a Linq Where call. Like this.
Context.Sources.Where(criteria.BuildQuery());
The exception was thrown when the expression is being evaluated/translated.
If I compile the expression and then pass a delegate to the Where call, everything works as expected.
Context.Sources.Where(criteria.BuildQuery().Compile());
I am not sure what difference it makes, if someone knows why please enlighten us.

Convert a Func<T> to Expression<Func<T>> for a known T [duplicate]

Since we can:
Expression<Func<int, bool>> predicate = x => x > 5;
var result = Enumerable.Range(0,10).Where(predicate.Compile());
How can I:
Func<int,bool> predicate = x => x > 5;
Expression<Func<int,bool>> exp = predicate.Decompile();
That is, I want to get the corresponding Expression of the Func. Is it possible?
There is no magic Decompile() for a delegate instance, short of deconstructing the IL (perhaps with mono.cecil). If you want an expression tree, you'll have to start with an expression tree, so have Expression<Func<int, bool>> througout.
As an edge case, you can get basic method delegate information from the delegate's .Method (the MethodInfo) and .Target (the arg0) - however, for most scenarios involving a lambda or anonymous method this will point at the compiler-generate method on the capture class, so won't really help you much. It is pretty much limited to scenarios like:
Func<string,int> parse = int.Parse;
Pass the lambda to a method that accepts an Expression<> and the C# compiler will pass you an expression tree at runtime. However this only works if you pass the lambda directly, not if you try to pass a delegate instance created from a lambda.
var exp = Decompile(x => x > 5);
public Expression<Func<int, bool>> Decompile(Expression<Func<int, bool>> exp)
{
return exp;
}
The closest option I've found for decompiling a delegate instance is detailed in this blog post from Jean-Baptiste Evain who works on the Mono team. He uses the excellent Mono.Cecil project to decompile the IL into a custom AST, then he maps it as best as possible into LINQ expressions.
You can try to use my library:
https://github.com/ashmind/expressive
Though it may not work as is for results of Compile(), since it is a DynamicMethod and getting IL of it is not straightforward. If you implement your own IManagedMethod implementation for DynamicMethod, though, it should just work.
I plan to implement DynamicMethod adapters, but do not yet know when.
You can’t decompile the delegate, but you can certainly create a new expression tree that simply calls the delegate:
Func<int, bool> predicate = x => x > 5;
Expression<Func<int, bool>> exp = x => predicate(x);

Creating, combining and caching lambda expressions

Say I have the following.
foreach (var loop in helper.Loop(x => x.LoopItems))
{
loop.Text(x => x.Name);
loop.Span(x => x.Name);
foreach (var loopItem in loop.Loop(x => x.NestedLoopItems))
{
loopItem.Text(x => x.Age);
}
}
This works just create with my current implementation, however it has to compile the inner lambda expression as many times as there are loop items. Currently this does something like this to create the expression to access a List<T> indexer. eg. x.ListItems[i]
var methodCallExpression = Expression.Call(_expression, ((PropertyInfo) _expression.Member).PropertyType.GetMethod("get_Item"), Expression.Constant(i));
var expression = Expression.Lambda<Func<TModel, T>>(methodCallExpression, _expression.GetParameter<TModel>());
It then does
var newExpression = CombineExpression(listExpression);
var enumerable = newExpression.Compile().Invoke(_htmlHelper.ViewData.Model);
And it is the compile step that seems to be the expensive one.
Would there be any way to cache this given the fact that it needs to create a new one for each loop, such that i in Expression.Constant(i) needs to increment each time modifying the expression.
I don't know what CombineExpression does but if you can change from Func<TModel, T> to Func<TModel, int, T> (assuming the indexer is always an int) if not you could add another generic to the method since you are already passing in "i" to get the Constant in the expression.
Also not entirely sure what type _expression is either so I don't know if this exactly is calling the overloads I think it is.
var parameterExpression = Expression.Parameter(typeof(int), "i");
var methodCallExpression = Expression.Call(_expression, ((PropertyInfo) _expression.Member).PropertyType.GetMethod("get_Item"), parameterExpression);
var expression = Expression.Lambda<Func<TModel, int, T>>(methodCallExpression, _expression.GetParameter<TModel>(), parameterExpression);
Then you could compile expression and get Func<TModel, int, T> and when invoking the Func you would pass in the "i" value.
Again since I don't know what CombineExpression does but if you get a strongly typed Func out of it you can just call it without the invoke.
Another side note why do expressions to get access to a list indexer? Why not just use IEnumerable<> or worst cast if you don't know they type but need the objects cast to IEnumerable (non-generic) and iterate over that?

Categories