Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.15.8" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\ExpressionTreesInCSharp\ExpressionTreesInCSharp.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using BenchmarkDotNet.Attributes;
using ExpressionTreesInCSharp;
using System.Linq.Expressions;

namespace Benchmarks;

[MemoryDiagnoser]
public class CompileBenchmarks
{
private readonly Expression<Func<int, int, int>> _sumExpressionTree =
ExpressionTrees.CreateExpressionTreeFromLambdaExpression();

private readonly Func<int, int, int> _lambda = ExpressionTrees.CreateLambdaExpression();
private Func<int, int, int> _compiled = default!;
private Func<int, int, int> _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);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
using BenchmarkDotNet.Running;

BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ public static Func<int, int, int> 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<int, int, int>)lambda.Compile();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.EntityFrameworkCore;
using System.Linq.Expressions;

namespace ExpressionTreesInCSharp.EntityFramework;
public class EntityFrameworkSqlite
Expand Down Expand Up @@ -26,4 +27,14 @@ public string GetWhereQuery()

return whereQuery;
}
}

public IEnumerable<User> FilterWithFunc(Func<User, bool> predicate)
{
return _dbContext.Users.Where(predicate);
}

public IQueryable<User> FilterWithExpression(Expression<Func<User, bool>> predicate)
{
return _dbContext.Users.Where(predicate);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,9 @@ public static Func<int, int, int> CompileExpressionTreeToLambdaExpression(Expres

return delegateRepresentingLambdaExpression;
}

public static Func<int, int, int> InterpretExpressionTree(Expression<Func<int, int, int>> expressionTree)
{
return expressionTree.Compile(preferInterpretation: true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.14" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -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<User>);
Assert.True(withExpression is IQueryable<User>);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,14 @@ public void GivenAnExpressionTree_WhenCompiled_ThenShouldExecuteAndReturnResult(

Assert.Equal(2, sum);
}
}

[Fact]
public void GivenAnExpressionTree_WhenInterpreted_ThenShouldReturnTheSameResult()
{
var expression = ExpressionTrees.CreateExpressionTreeFromLambdaExpression();

var interpretedSum = ExpressionTrees.InterpretExpressionTree(expression);

Assert.Equal(3, interpretedSum(1, 2));
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

Expand All @@ -10,14 +10,14 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="Moq" Version="4.18.4" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.11.0" />
<PackageReference Include="Moq" Version="4.21.0" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="4.0.1">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.2.0">
<PackageReference Include="coverlet.collector" Version="10.1.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
Expand Down
Loading