Multiply two lambda with Expression - c#

Basically I am trying to multiply two lambdas with the class Expression but I don't even manage to build and can't find documentation on this. Here is my code:
var f = x=>x+2;
var g = x=>x+3;
var argX = Expression.Parameter(typeof(double), "x");
var fg = Expression.Multiply(Expression.Constant(g, typeof(Func<double, double>)), Expression.Constant(f, typeof(Func<double, double>)));
//var fg = Expression.Multiply(Expression.Constant(g),Expression.Constant(f));
var lambda = Expression.Lambda<Func<double, double>>(f3, argX);
return lambda.Compile();

Do you want something like this:
Expression<Func<double,double>> f = x => x + 2;
Expression<Func<double,double>> g = x => x + 3;
var param = Expression.Parameter(typeof(double));
var invokeF = Expression.Invoke(f, param);
var invokeG = Expression.Invoke(g, param);
var mult = Expression.Multiply(invokeF,invokeG);
var lambda = ((Expression<Func<double, double>>)Expression.Lambda(mult, param)).Compile();
If i call it this way:
lambda(3);
I get 30 as valid answer.

For this simply define f and g as Expression as well:
var argX = Expression.Parameter(typeof(double), "x");
var f = Expression.Add(argX, Expression.Constant(3.0)); // applies to x => x + 3
var g = Expression.Add(argX, Expression.Constant(2.0)); // applies to x => x + 2
var fg = Expression.Multiply(f, g); // applies to f(x) * g(x)
var lambda = Expression.Lambda<Func<double, double>>(fg, argX);
Now call it like this:
var r = lambda.Compile()(1);
Which returns 12.

Related

How to convert linq query with joins to method syntax?

I want to change this to lambda query in c#
var innerJoinTasinmaz =
from tasin in _context.Tasinmaz
join mahalle in _context.Mahalle on tasin.MahalleID equals mahalle.AreaID
join ilce in _context.Ilce on tasin.CountyID equals ilce.CountyID
join il in _context.Il on tasin.CityID equals il.CityID
select new{
tasinmazID = tasin.TasinmazID,
cityName = il.CityName,
countyName = ilce.CountyName,
areaName = mahalle.AreaName,
ada = tasin.Ada,
parsel = tasin.Parsel,
nitelik = tasin.Nitelik,
adres = tasin.Adres,
isActive = tasin.isActive,
};
I am struggling to write it in Lambda Expression. Any help would be greatly appreciated.
You'll need the Join method which takes four parameters:
the enumerable that you want to join
a selector in the first enumerable
a selector in the second enumerable
a selector for both enumerables
It is compared whether the values from 2 und 3 are the same, and if so, the selector from 4 is used to choose which properties you want to use. In your example, it would look like:
var innerJoinTasinmaz =
_context.Tasinmaz
.Join(_context.Mahalle, x => x.MahalleId, y => y.AreaID, (x, y) => new { tasin = x, mahalle = y })
.Join(_context.Ilce, x => x.CountyID, y => y.CountyId, (x, y) => new { tasin = x.tasin, mahalle = x.mahalle, ilce = y })
.Join(_context.Il, x => x.CityId, y => y.CityId, (x, y) => new
{
tasinmazId = x.tasin.TasinmazID,
cityName = y.CityName,
countyName = x.ilce.CountyName,
areaName = x.mahalle.AreaName,
ada = x.tasin.Ada,
parsel = x.tasin.Parsel,
nitelik = x.tasin.Nitelik,
adres = x.tasin.Adres,
isActive = x.tasin.isActive,
});
You can think about whether method or query syntax is more readable.

How to detect closures in code with Roslyn?

Can I detect (using roslyn) that x reference in the lambda body is closure over outer variable x, not some variable local to lambda itself?
var x = "foo";
var a = string[0];
a.Any(i => i == x);
Yup. You can use the DataFlowAnalysis API.
var tree = CSharpSyntaxTree.ParseText(
#"
class C{
void M(){
var x = ""foo"";
var a = new string[0];
var testing = a.Any(i => i == x);
}
}
");
var Mscorlib = PortableExecutableReference.CreateFromAssembly(typeof(object).Assembly);
var compilation = CSharpCompilation.Create("MyCompilation",
syntaxTrees: new[] { tree }, references: new[] { Mscorlib });
var model = compilation.GetSemanticModel(tree);
var lambda = tree.GetRoot().DescendantNodes().OfType<LocalDeclarationStatementSyntax>().Last();
var dataFlowAnalysis = model.AnalyzeDataFlow(lambda);
var capturedVariables = dataFlowAnalysis.Captured;
foreach(var variable in capturedVariables)
{
//Do something
}
https://github.com/mjsabby/RoslynClrHeapAllocationAnalyzer/blob/master/ClrHeapAllocationsAnalyzer/DisplayClassAllocationAnalyzer.cs#L58
(1) Get Semantic Model
(2) Check for AnonymousMethodExpressionSyntax / SimpleLambdaExpressionSyntax / ParenthesizedLambdaExpressionSyntax
(3) Pass that node to AnalyzeDataFlow extension method on the SemanticModel
(4) Iterate over the .Captured property

Expressions... What am I doing wrong?

I've decided to take some golden time to learn a bit more about Expressions. I'm trying a very simple exercise, namely adding two numbers. I've hit an exception that's proving to be tricky to search for.
Here's my code
Expression<Func<int,int,int>> addExpr = (x, y) => x + y;
var p1 = Expression.Parameter(typeof(int), "p1");
var p2 = Expression.Parameter(typeof(int), "p2");
var lambda = Expression.Lambda<Func<int,int,int>>(addExpr, p1, p2); //<-here
var del = lambda.Compile();
var result = del(2,3); //expect 5
but this is throwing an ArgumentException : Expression of type 'System.Func`3[System.Int32,System.Int32,System.Int32]' cannot be used for return type 'System.Int32'
at the line indicated above. What have I done wrong?
You need to wrap the addExpr in an invoke using the expression parameters
Expression<Func<int,int,int>> addExpr = (x, y) => x + y;
var p1 = Expression.Parameter(typeof(int), "p1");
var p2 = Expression.Parameter(typeof(int), "p2");
var invokeExpression=Expression.Invoke(addExpr,p1,p2);
var lambda = Expression.Lambda<Func<int,int,int>>(invokeExpression,p1,p2);
var del = lambda.Compile();
var result=del(2,3);
The invoke is how you type p1 to x and p2 to y, alternatively you could just write the above as
var p1 = Expression.Parameter(typeof(int), "p1");
var p2 = Expression.Parameter(typeof(int), "p2");
var lambda=Expresion.Lambda<Func<int,int,int>>(Expression.Add(p1,p2),p1,p2);
var del = lambda.Compile();
var result=del(2,3);
Otherwise you need to grab the expression body into the lambda and pass the expression parameters.
var lambda=Expresion.Lambda<Func<int,int,int>>(addExpr.Body,addExpr.Parameters);
Your code should be:
var lambda = Expression.Lambda<Func<Expression<Func<int, int, int>>, int, int>(addExpr, p1, p2);
Your current code expects an int and your passing in Expression<Func<int, int, int>>.
Update
Actually the above won't compile, you would need to do:
var lambda = Expression.Lambda<Func<int, int, int>>(Expression.Add(p1, p2), p1, p2);
You need to decompose addExpr's body or preferably just write it from scratch ie Expression.Add(p1,p2) instead of addExpr.

Is there a bug with nested invoke of LambdaExpression?

I tried to compile and calculate LambdaExpression like:
Plus(10, Plus(1,2))
But result is 4, not 13.
Code:
using System;
using System.Linq.Expressions;
namespace CheckLambdaExpressionBug
{
class Program
{
static void Main(string[] _args)
{
ParameterExpression p1 = Expression.Parameter(typeof (int), "p1");
ParameterExpression p2 = Expression.Parameter(typeof (int), "p2");
LambdaExpression lambda = Expression.Lambda(Expression.Call(typeof(Program).GetMethod("Plus"), p1, p2), p1, p2);
InvocationExpression exp1 = Expression.Invoke(
lambda,
Expression.Constant(1),
Expression.Constant(2)
);
InvocationExpression exp2 = Expression.Invoke(
lambda,
Expression.Constant(10),
exp1
);
var func = (Func<int>) Expression.Lambda(exp2).Compile();
int v = func();
Console.Out.WriteLine("Result = {0}", v);
}
public static int Plus(int a, int b)
{
return a + b;
}
}
}
Since nobody seems to be posting this:
It looks to be a bug in .NET 3.5, and is fixed in .NET 4.
whereas this seems to produce 13 in 3.5 too:
var plus = new Func<int, int, int>((a, b) => a + b);
var func = new Func<int>(() => plus(10, plus(1, 2)));
var res = func();
Console.WriteLine(res);
maybe i needs to assign the result to a local var
try this
var plus = new Func((a, b) => a + b);
var puls_1 = plus(1, 2);
var func = new Func(() => plus(10, plus_1));
var res = func();
Console.WriteLine(res);

Equivalent lambda syntax for linq query

I am having a mind-freeze here, but I cant seem to find the equivalent lambda syntax for -
string[] a = {"a","b","c"};
string[] b = {"1","2","3"};
var x = from a1 in a
from b1 in b
select new{a1, b1};
var x = a.SelectMany(a1=>b.Select(b1=>new {a1,b1}));
ReSharper says:
var x = a.SelectMany(a1 => b, (a1, b1) => new { a1, b1 });

Categories

Resources