diff --git a/csharp-advanced-topics/ExpressionTreesInCSharp/Benchmarks/Benchmarks.csproj b/csharp-advanced-topics/ExpressionTreesInCSharp/Benchmarks/Benchmarks.csproj
new file mode 100644
index 0000000000..d3c17d10a2
--- /dev/null
+++ b/csharp-advanced-topics/ExpressionTreesInCSharp/Benchmarks/Benchmarks.csproj
@@ -0,0 +1,18 @@
+
+
+
+ Exe
+ net10.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
diff --git a/csharp-advanced-topics/ExpressionTreesInCSharp/Benchmarks/CompileBenchmarks.cs b/csharp-advanced-topics/ExpressionTreesInCSharp/Benchmarks/CompileBenchmarks.cs
new file mode 100644
index 0000000000..c7112007ff
--- /dev/null
+++ b/csharp-advanced-topics/ExpressionTreesInCSharp/Benchmarks/CompileBenchmarks.cs
@@ -0,0 +1,38 @@
+using BenchmarkDotNet.Attributes;
+using ExpressionTreesInCSharp;
+using System.Linq.Expressions;
+
+namespace Benchmarks;
+
+[MemoryDiagnoser]
+public class CompileBenchmarks
+{
+ private readonly Expression> _sumExpressionTree =
+ ExpressionTrees.CreateExpressionTreeFromLambdaExpression();
+
+ private readonly Func _lambda = ExpressionTrees.CreateLambdaExpression();
+ private Func _compiled = default!;
+ private Func _interpreted = default!;
+
+ [GlobalSetup]
+ public void Setup()
+ {
+ _compiled = _sumExpressionTree.Compile();
+ _interpreted = _sumExpressionTree.Compile(preferInterpretation: true);
+ }
+
+ [Benchmark]
+ public int InvokeLambda() => _lambda(1, 2);
+
+ [Benchmark]
+ public int InvokeCachedCompiledDelegate() => _compiled(1, 2);
+
+ [Benchmark]
+ public int InvokeCachedInterpretedDelegate() => _interpreted(1, 2);
+
+ [Benchmark]
+ public int CompileAndInvoke() => _sumExpressionTree.Compile()(1, 2);
+
+ [Benchmark]
+ public int InterpretAndInvoke() => _sumExpressionTree.Compile(preferInterpretation: true)(1, 2);
+}
diff --git a/csharp-advanced-topics/ExpressionTreesInCSharp/Benchmarks/Program.cs b/csharp-advanced-topics/ExpressionTreesInCSharp/Benchmarks/Program.cs
new file mode 100644
index 0000000000..c9a046727c
--- /dev/null
+++ b/csharp-advanced-topics/ExpressionTreesInCSharp/Benchmarks/Program.cs
@@ -0,0 +1,3 @@
+using BenchmarkDotNet.Running;
+
+BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);
diff --git a/csharp-advanced-topics/ExpressionTreesInCSharp/ExpressionTreesInCSharp.sln b/csharp-advanced-topics/ExpressionTreesInCSharp/ExpressionTreesInCSharp.sln
index e59a24efd4..e1a50157f9 100644
--- a/csharp-advanced-topics/ExpressionTreesInCSharp/ExpressionTreesInCSharp.sln
+++ b/csharp-advanced-topics/ExpressionTreesInCSharp/ExpressionTreesInCSharp.sln
@@ -7,20 +7,54 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExpressionTreesInCSharp", "
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{1421730A-00C5-44F5-98F4-8E6623F7C3C5}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Benchmarks", "Benchmarks\Benchmarks.csproj", "{17A874D8-A920-4912-8E62-1B43E8176375}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{DD0C1186-0518-4FA7-89A9-5101A346045C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DD0C1186-0518-4FA7-89A9-5101A346045C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DD0C1186-0518-4FA7-89A9-5101A346045C}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {DD0C1186-0518-4FA7-89A9-5101A346045C}.Debug|x64.Build.0 = Debug|Any CPU
+ {DD0C1186-0518-4FA7-89A9-5101A346045C}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {DD0C1186-0518-4FA7-89A9-5101A346045C}.Debug|x86.Build.0 = Debug|Any CPU
{DD0C1186-0518-4FA7-89A9-5101A346045C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DD0C1186-0518-4FA7-89A9-5101A346045C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DD0C1186-0518-4FA7-89A9-5101A346045C}.Release|x64.ActiveCfg = Release|Any CPU
+ {DD0C1186-0518-4FA7-89A9-5101A346045C}.Release|x64.Build.0 = Release|Any CPU
+ {DD0C1186-0518-4FA7-89A9-5101A346045C}.Release|x86.ActiveCfg = Release|Any CPU
+ {DD0C1186-0518-4FA7-89A9-5101A346045C}.Release|x86.Build.0 = Release|Any CPU
{1421730A-00C5-44F5-98F4-8E6623F7C3C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1421730A-00C5-44F5-98F4-8E6623F7C3C5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1421730A-00C5-44F5-98F4-8E6623F7C3C5}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {1421730A-00C5-44F5-98F4-8E6623F7C3C5}.Debug|x64.Build.0 = Debug|Any CPU
+ {1421730A-00C5-44F5-98F4-8E6623F7C3C5}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {1421730A-00C5-44F5-98F4-8E6623F7C3C5}.Debug|x86.Build.0 = Debug|Any CPU
{1421730A-00C5-44F5-98F4-8E6623F7C3C5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1421730A-00C5-44F5-98F4-8E6623F7C3C5}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1421730A-00C5-44F5-98F4-8E6623F7C3C5}.Release|x64.ActiveCfg = Release|Any CPU
+ {1421730A-00C5-44F5-98F4-8E6623F7C3C5}.Release|x64.Build.0 = Release|Any CPU
+ {1421730A-00C5-44F5-98F4-8E6623F7C3C5}.Release|x86.ActiveCfg = Release|Any CPU
+ {1421730A-00C5-44F5-98F4-8E6623F7C3C5}.Release|x86.Build.0 = Release|Any CPU
+ {17A874D8-A920-4912-8E62-1B43E8176375}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {17A874D8-A920-4912-8E62-1B43E8176375}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {17A874D8-A920-4912-8E62-1B43E8176375}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {17A874D8-A920-4912-8E62-1B43E8176375}.Debug|x64.Build.0 = Debug|Any CPU
+ {17A874D8-A920-4912-8E62-1B43E8176375}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {17A874D8-A920-4912-8E62-1B43E8176375}.Debug|x86.Build.0 = Debug|Any CPU
+ {17A874D8-A920-4912-8E62-1B43E8176375}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {17A874D8-A920-4912-8E62-1B43E8176375}.Release|Any CPU.Build.0 = Release|Any CPU
+ {17A874D8-A920-4912-8E62-1B43E8176375}.Release|x64.ActiveCfg = Release|Any CPU
+ {17A874D8-A920-4912-8E62-1B43E8176375}.Release|x64.Build.0 = Release|Any CPU
+ {17A874D8-A920-4912-8E62-1B43E8176375}.Release|x86.ActiveCfg = Release|Any CPU
+ {17A874D8-A920-4912-8E62-1B43E8176375}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/csharp-advanced-topics/ExpressionTreesInCSharp/ExpressionTreesInCSharp/DynamicMethods/DynamicMethodGenerator.cs b/csharp-advanced-topics/ExpressionTreesInCSharp/ExpressionTreesInCSharp/DynamicMethods/DynamicMethodGenerator.cs
index c32e1d7a27..0bb966a1e6 100644
--- a/csharp-advanced-topics/ExpressionTreesInCSharp/ExpressionTreesInCSharp/DynamicMethods/DynamicMethodGenerator.cs
+++ b/csharp-advanced-topics/ExpressionTreesInCSharp/ExpressionTreesInCSharp/DynamicMethods/DynamicMethodGenerator.cs
@@ -13,8 +13,8 @@ public static Func GenerateExecutableFunctionFromMathStatement(st
var right = Expression.Parameter(typeof(int), variables[1]);
// Create the expression tree
- var add = Expression.Multiply(left, right);
- var lambda = Expression.Lambda(add, left, right);
+ var product = Expression.Multiply(left, right);
+ var lambda = Expression.Lambda(product, left, right);
// Return the compiled method
return (Func)lambda.Compile();
diff --git a/csharp-advanced-topics/ExpressionTreesInCSharp/ExpressionTreesInCSharp/EntityFramework/EntityFrameworkSqlite.cs b/csharp-advanced-topics/ExpressionTreesInCSharp/ExpressionTreesInCSharp/EntityFramework/EntityFrameworkSqlite.cs
index 29700f2ed5..62e9310e1f 100644
--- a/csharp-advanced-topics/ExpressionTreesInCSharp/ExpressionTreesInCSharp/EntityFramework/EntityFrameworkSqlite.cs
+++ b/csharp-advanced-topics/ExpressionTreesInCSharp/ExpressionTreesInCSharp/EntityFramework/EntityFrameworkSqlite.cs
@@ -1,4 +1,5 @@
using Microsoft.EntityFrameworkCore;
+using System.Linq.Expressions;
namespace ExpressionTreesInCSharp.EntityFramework;
public class EntityFrameworkSqlite
@@ -26,4 +27,14 @@ public string GetWhereQuery()
return whereQuery;
}
-}
\ No newline at end of file
+
+ public IEnumerable FilterWithFunc(Func predicate)
+ {
+ return _dbContext.Users.Where(predicate);
+ }
+
+ public IQueryable FilterWithExpression(Expression> predicate)
+ {
+ return _dbContext.Users.Where(predicate);
+ }
+}
diff --git a/csharp-advanced-topics/ExpressionTreesInCSharp/ExpressionTreesInCSharp/ExpressionTrees.cs b/csharp-advanced-topics/ExpressionTreesInCSharp/ExpressionTreesInCSharp/ExpressionTrees.cs
index c3c1ec5dad..4ecc9c1469 100644
--- a/csharp-advanced-topics/ExpressionTreesInCSharp/ExpressionTreesInCSharp/ExpressionTrees.cs
+++ b/csharp-advanced-topics/ExpressionTreesInCSharp/ExpressionTreesInCSharp/ExpressionTrees.cs
@@ -33,4 +33,9 @@ public static Func CompileExpressionTreeToLambdaExpression(Expres
return delegateRepresentingLambdaExpression;
}
+
+ public static Func InterpretExpressionTree(Expression> expressionTree)
+ {
+ return expressionTree.Compile(preferInterpretation: true);
+ }
}
diff --git a/csharp-advanced-topics/ExpressionTreesInCSharp/ExpressionTreesInCSharp/ExpressionTreesInCSharp.csproj b/csharp-advanced-topics/ExpressionTreesInCSharp/ExpressionTreesInCSharp/ExpressionTreesInCSharp.csproj
index 554375c136..19b1557167 100644
--- a/csharp-advanced-topics/ExpressionTreesInCSharp/ExpressionTreesInCSharp/ExpressionTreesInCSharp.csproj
+++ b/csharp-advanced-topics/ExpressionTreesInCSharp/ExpressionTreesInCSharp/ExpressionTreesInCSharp.csproj
@@ -2,13 +2,13 @@
Exe
- net7.0
+ net10.0
enable
enable
-
+
diff --git a/csharp-advanced-topics/ExpressionTreesInCSharp/Tests/EntityFrameworkTests.cs b/csharp-advanced-topics/ExpressionTreesInCSharp/Tests/EntityFrameworkTests.cs
index 9d62baf5de..2a45c4666c 100644
--- a/csharp-advanced-topics/ExpressionTreesInCSharp/Tests/EntityFrameworkTests.cs
+++ b/csharp-advanced-topics/ExpressionTreesInCSharp/Tests/EntityFrameworkTests.cs
@@ -33,4 +33,16 @@ public void GivenAUserDbContext_WhenListedUsersWithFilters_ThenShouldUseCorrectQ
Assert.Equal(expectedQuery, query);
}
+
+ [Fact]
+ public void GivenAFuncPredicate_WhenFiltering_ThenTheQueryLeavesEntityFramework()
+ {
+ var efSqlite = new EntityFrameworkSqlite();
+
+ var withFunc = efSqlite.FilterWithFunc(x => x.Age > 20);
+ var withExpression = efSqlite.FilterWithExpression(x => x.Age > 20);
+
+ Assert.False(withFunc is IQueryable);
+ Assert.True(withExpression is IQueryable);
+ }
}
diff --git a/csharp-advanced-topics/ExpressionTreesInCSharp/Tests/ExpressionTreeTests.cs b/csharp-advanced-topics/ExpressionTreesInCSharp/Tests/ExpressionTreeTests.cs
index fb7da83460..f666f39b31 100644
--- a/csharp-advanced-topics/ExpressionTreesInCSharp/Tests/ExpressionTreeTests.cs
+++ b/csharp-advanced-topics/ExpressionTreesInCSharp/Tests/ExpressionTreeTests.cs
@@ -70,4 +70,14 @@ public void GivenAnExpressionTree_WhenCompiled_ThenShouldExecuteAndReturnResult(
Assert.Equal(2, sum);
}
-}
\ No newline at end of file
+
+ [Fact]
+ public void GivenAnExpressionTree_WhenInterpreted_ThenShouldReturnTheSameResult()
+ {
+ var expression = ExpressionTrees.CreateExpressionTreeFromLambdaExpression();
+
+ var interpretedSum = ExpressionTrees.InterpretExpressionTree(expression);
+
+ Assert.Equal(3, interpretedSum(1, 2));
+ }
+}
diff --git a/csharp-advanced-topics/ExpressionTreesInCSharp/Tests/Tests.csproj b/csharp-advanced-topics/ExpressionTreesInCSharp/Tests/Tests.csproj
index f7ba662f76..6d962eb27b 100644
--- a/csharp-advanced-topics/ExpressionTreesInCSharp/Tests/Tests.csproj
+++ b/csharp-advanced-topics/ExpressionTreesInCSharp/Tests/Tests.csproj
@@ -1,7 +1,7 @@
- net7.0
+ net10.0
enable
enable
@@ -10,14 +10,14 @@
-
-
-
-
+
+
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all