I want to validate my assumption that the LINQ Expression API does not have any means for us to create an expression that represents the creation of a local variable.
In other words, you cannot create an expression to represent:
int local;
since that is a variable declaration statement, and the API does not support statement lambdas. The only state that a lambda expression, as represented by the LINQ Expression API (and not a delegate instance) can work with is parameters it receives and the captured variables it receives via a closure.
Is my assumption (based on a few months of practice of the LINQ Expression API) correct?
False. There are some overloads of Expression.Block to do it.
What is true is that you can't create a lambda expression through the use of the C# compiler that has a variable, but that is a limitation of the compiler.
So you can't
Expression<Func<int>> exp = () => {
int v = 1;
return v;
};
but you can
var variable = Expression.Variable(typeof(int));
var lambda = Expression.Lambda<Func<int>>(
Expression.Block(
new[] { variable },
Expression.Assign(variable, Expression.Constant(1)),
variable)); // With lambda expressions, there is an implicit
// return of the last value "loaded" on the stack
since that is a variable declaration statement, and the API does not support statement lambdas.
This was true in .NET < 4.0 . In .NET 4.0 Microsoft added Expression methods to build nearly everything that can be present in the body of a method (there are some missing "things", like unsafe code keywords/operators, plus there are the primitives but there aren't complex constructs like the for or lock, that can be built on top of other constructs). Note that 90% of those added things are incompatible with LINQ-to-SQL/EF.
Well, you can use Expression.Block to declare a block which contains local variables...
For example:
using System;
using System.Linq.Expressions;
public class Test
{
static void Main()
{
var x = Expression.Variable(typeof(int), "x");
var assignment1 = Expression.Assign(x, Expression.Constant(1, typeof(int)));
var assignment2 = Expression.Assign(x, Expression.Constant(2, typeof(int)));
var block = Expression.Block(new[] { x }, new[] { assignment1, assignment2 });
}
}
That builds an expression tree equivalent to:
{
int x;
x = 1;
x = 2;
}
The C# compiler doesn't use this functionality within lambda expression conversions to expression trees, which are currently still restricted to expression lambdas, as far as I'm aware.
Related
I am trying to dynamically generate a class that implements a given interface. Because of this, I need to implement some methods. I would like to avoid directly emitting IL instructions, so I am trying to use Expression trees and CompileToMethod. Unfortunately, some of these methods need to access a field of the generated class (as if I wrote this.field into the method I am implementing). Is it possible to access "this" using expression trees? (By "this" I mean the object the method will be called on.)
If yes, what would a method like this look like with expression trees?
int SomeMethod() {
return this.field.SomeOtherMethod();
}
Expression.Constant or ParameterExpression are your friends; examples:
var obj = Expression.Constant(this);
var field = Expression.PropertyOrField(obj, "field");
var call = Expression.Call(field, field.Type.GetMethod("SomeOtherMethod"));
var lambda = Expression.Lambda<Func<int>>(call);
or:
var obj = Expression.Parameter(typeof(SomeType));
var field = Expression.PropertyOrField(obj, "field");
var call = Expression.Call(field, field.Type.GetMethod("SomeOtherMethod"));
var lambda = Expression.Lambda<Func<SomeType, int>>(call, obj);
(in the latter case, you'd pass this in as a parameter, but it means you can store the lambda and re-use it for different target instance objects)
Another option here might be dynamic if your names are fixed:
dynamic obj = someDuckTypedObject;
int i = obj.field.SomeOtherMethod();
I am new to the C# and .NET world. I am trying to understand the following statement.
var xyz = Enumerable.Repeat(obj, 1).ToList();
var abc =
xyz.Select(xyzobj => new res {
foo = bar,
xyzs = new [] {xyzobj},
}).ToList();
I understand that Select takes in an object and a transformer function and returns a new form of the object. But here, it takes in a lambda expression with an enum value and another object.
I am little confused. Is the statement above similar to
var abc = xyz.Select(xyzobj => {
//some work with xyzobj
//and return object.
}).ToList();
Can somebody explain the above statement actually does, my head just spins around with these statements all around in my new work location.
Can somebody direct me to good resources to understand lambda expressions and Enumeration.
There are two main types of lambda expressions in C#.
Expression lambdas like this:
x => foo(x);
This takes a parameter x, and performs some transformation on it, foo, returning the result of foo(x) (though technically it may not return a value of the result type of foo(x) is void).
Statement lambdas look like this:
x => {
// code block
}
This takes a parameter, x and performs some action on it, (optionally returning a value if an explicit return is provided). The code block may be composed of multiple statements, meaning you can declare variables, execute loops, etc. This is not supported in the simpler expression lambda syntax. But it's just another type of lambda.
If it helps you can think of the following as being equivalent (although they are not perfectly equivalent if you are trying to parse this as an Expression):
x => foo(x);
x => { return foo(x); }
Further Reading
Lambda Expressions (C# Programming Guide)
// Creates a IEnumerable<T> of the type of obj with 1 element and converts it to a List
var xyz = Enumerable.Repeat(obj, 1).ToList();
// Select takes each element in the List xyz
// and passes it to the lambda as the parameter xyzobj.
// Each element is used to create a new res object with object initialization.
// The res object has two properties, foo and xyzs. foo is given the value bar
// (which was defined elsewhere).
// The xyzs property is created using the element from xyz passed into the lambda
var abc = xyz.Select(
xyzobj => new res {
foo = bar,
xyzs = new [] {xyzobj},
}).ToList();
I am using reflection to call methods, and invoking the methods using Invoke() doesn't do it for me, too slow. I generate thousands - millions of method calls, it is a test automation tool. At compile time I have no clue about the method name, parameter type(s) or return type. So Jon Skeet's article on using delegates to cache reflection is no help here.
Here is what I have:
foreach (MethodInfo method in _methods)
{
foreach (var p in method.GetParameters())
{
var paramValue = Utils.RandomizeParamValue(p.ParameterType.Name);
parameters.Add(paramValue);
}
var result = method.Invoke(_objectInstance, parameters.ToArray());
//_objectInstance is the class instance of which the method is a member of.
}
I have researched the DLR (ExpandoObject, DynamicObject) but I am not sure it has what I am looking for. What I am looking for is a way to bypass the overhead of reflection, or cache method invocations, even if it turns out be an ugly hack. Is there a common hack that I have missed? Could I go down to IL level and do some tricks there?
One option is to use expression tree to build delegate that will call your methods. MSDN have introduction in Expression Trees article and in particular you'll need MethodCallExpression
Create an expression sample (from MethodCallExpression article):
string[,] gradeArray =
{ {"chemistry", "history", "mathematics"}, {"78", "61", "82"} };
var arrayExpression = Expression.Constant(gradeArray);
// Create a MethodCallExpression that represents indexing
// into the two-dimensional array 'gradeArray' at (0, 2).
// Executing the expression would return "mathematics".
var methodCallExpression = Expression.ArrayIndex(
arrayExpression,
Expression.Constant(0),
Expression.Constant(2));
Compile an expression to delegate sample (from main article):
Expression<Func<int, bool>> expr = num => num < 5;
Func<int, bool> result = expr.Compile();
Console.WriteLine(result(4));
What are C# lambda's compiled into? A stackframe, an instance of an anonymous type, or?
I've read this question. Which mostly answers "why" you can't use a lambda when also using implicit type features. But, this question is aimed at answering what construct the compiler produces to actually carry out the code of a lambda. Is it a method call of an anonymous type (something like anonymous types that implement an interface in Java?) or is it just a stack frame with references to closed variables and the accepting the parameter signature? Some lambda's don't close over anything -- so are there then 2 different resulting outputs from the compile.
Assuming you mean "as a delegate", then it still depends :p if it captures any variables (including "this", which may be implicit) then those variables are actually implemented as fields on a compiler-generated type (not exposed anywhere public), and the statement body becomes a method on that capture class. If there are multiple levels of capture, the outer capture is again a field on the inner capture class. But essentially:
int i = ...
Func<int,int> func = x => 2*x*i;
Is like;
var capture = new SecretType();
capture.i = ...
Func<int,int> func = capture.SecretMethod;
Where:
class SecretType {
public int i;
public int SecretMethod(int x) { return 2*x*i; }
}
This is identical to "anonymous methods", but with different syntax.
Note that methods that do not capture state may be implemented as static methods without a capture class.
Expression trees, on the other hand... Are trickier to explain :p
But (I don't have a compiler to hand, so bear with me):
int i = ...
Expression<Func<int,int>> func = x => 2*x*i;
Is something like:
var capture = new SecretType();
capture.i = ...
var p = Expression.Parameter("x", typeof(int));
Expression<Func<int,int>> func = Expression.Lambda<Func<int,int>>(
Expression.Multiply(
Expression.Multiply(Expression.Constant(2),p),
Expression.PropertyOrField(Expression.Constant(capture), "i")
), p);
(except using the non-existent "memberof" construct, since the compiler can cheat)
Expression trees are complex, but can be deconstructed and inspected - for example to translate into TSQL.
Lambda expressions are indeed anonymous functions, but with more versatility. These two articles authored by the MSDN have a lot of information on lambda expressions, how to use them, what precedence the operator => has, what their relation to anonymous functions are, and some advanced suggestions of use.
Lambda Expressions (MSDN)
=> Operator (MSDN)
Here are some examples:
public class C
{
private int field = 0;
public void M()
{
int local = 0;
Func<int> f1 = () => 0;
// f1 is a delegate that references a compiler-generated static method in C
Func<int> f2 = () => this.field;
// f2 is a delegate that references a compiler-generated instance method in C
Func<int> f3 = () => local;
// f3 is a delegate that references an instance method of a compiler-generated nested class in C
}
}
A lambda expression is an unnamed method written in place of delegate istance.
The compiler converts it to either:
A delegate instance
An expression tree, of type Expression<TDelegate> that representing the code inside, in a traversable object model. This allows the lambda expression to be interpreted at runtime.
So the compiler solves lambda expressions moving the expression's code into a private method.
I had a part of code that takes in lambda expressions at runtime, which I can then compile and invoke.
Something thing;
Expression<Action<Something>> expression = (c => c.DoWork());
Delegate del = expression.Compile();
del.DynamicInvoke(thing);
In order to save execution time, I stored those compiled delegates in a cache, a Dictionary<String, Delegate> which the key is the lambda expression string.
cache.Add("(Something)c => c.DoWork()", del);
For exact same calls, it worked fine. However I realized that I could receive equivalent lambdas, such as "d => d.DoWork()", which I should actually use the same delegate for, and I wasn't.
This got me wondering if there was a clean way (read "not using String.Replace", I already did that as a temporary fix) to replace the elements in a lambda expression, like maybe replacing them by arg0 so that both
(c => c.DoWork()) and (d => d.DoWork())
are transformed and compared as (arg0 => arg0.DoWork()) by using something fuctionnally similar to injecting a Expression.Parameter(Type, Name) in a lambda.
Is that possible ? (Answers can include C#4.0)
I used strings, since it was the easisest way for me. You can't manually change the name of the parameter expression (it has the "Name" property, but it is read-only), so you must construct a new expression from pieces. What I did is created a "nameless" parameter (actually, it gets an autogenerated name in this case, which is "Param_0") and then created a new expression almost the same as the old one, but using the new parameter.
public static void Main()
{
String thing = "test";
Expression<Action<String>> expression = c => c.ToUpper();
Delegate del = expression.Compile();
del.DynamicInvoke(thing);
Dictionary<String, Delegate> cache = new Dictionary<String, Delegate>();
cache.Add(GenerateKey(expression), del);
Expression<Action<String>> expression1 = d => d.ToUpper();
var test = cache.ContainsKey(GenerateKey(expression1));
Console.WriteLine(test);
}
public static string GenerateKey(Expression<Action<String>> expr)
{
ParameterExpression newParam = Expression.Parameter(expr.Parameters[0].Type);
Expression newExprBody = Expression.Call(newParam, ((MethodCallExpression)expr.Body).Method);
Expression<Action<String>> newExpr = Expression.Lambda<Action<String>>(newExprBody, newParam);
return newExpr.ToString();
}
There's more to a lambda expression than just the text. Lambdas are re-written by the compiler into something much more complicated. For example, they may close over variables (which could include other delegates). This means that two lambdas could look exactly the same, but perform completely different actions.
So you might have luck caching your compiled expression, but you need to give them a more meaningful name for the key than just the text of the expression. Otherwise no amount of argument substitution will help you.