The Griffin+ Expressions Library contains helpers that come in handy when working with LINQ expressions.
It provides the following features:
- Inlining Lambda Expressions
- Composing Lambda Expressions
- Comparing Expressions
The library follows semantic versioning, so it should be safe to use higher versions of the library, as long as the major version number does not change.
The library is entirely written in C# using .NET Standard 2.0.
A more specific build for .NET Framework 4.6.1 minimizes dependencies on framework components.
Therefore it should work on the following platforms (or higher):
- .NET Framework 4.6.1
- .NET Core 2.2
- .NET Core 3.1
- .NET 5/6/7/8
- Mono 5.4
- Xamarin iOS 10.14
- Xamarin Mac 3.8
- Xamarin Android 8.0
- Universal Windows Platform (UWP) 10.0.16299
The library is tested automatically on the following frameworks and operating systems:
- .NET Framework 4.6.1: Tests with library built for .NET Framework 4.6.1 (Windows Server 2022)
- .NET Framework 4.8: Tests with library built for .NET Framework 4.6.1 (Windows Server 2022)
- .NET Core 2.2: Tests with library built for .NET Standard 2.0 (Windows Server 2022 and Ubuntu 22.04)
- .NET Core 3.1: Tests with library built for .NET Standard 2.0 (Windows Server 2022 and Ubuntu 22.04)
- .NET 5.0: Tests with library built for .NET Standard 2.0 (Windows Server 2022 and Ubuntu 22.04)
- .NET 6.0: Tests with library built for .NET Standard 2.0 (Windows Server 2022 and Ubuntu 22.04)
- .NET 7.0: Tests with library built for .NET Standard 2.0 (Windows Server 2022 and Ubuntu 22.04)
- .NET 8.0: Tests with library built for .NET Standard 2.0 (Windows Server 2022 and Ubuntu 22.04)
The Griffin+ Expressions Library ships everything in the GriffinPlus.Lib.Expressions
namespace.
Usually lambda expressions have to be assigned to a variable before they can be used elsewhere, because the compiler
cannot infer the parameter types and the return type from a lambda expression. This prevents expressions from being
used inline. The static EXPR
methods in the LambdaExpressionInliners
class help to circumvent this limitation.
These generic methods mimic the signature of the desired lambda expression and return the specified lambda expression
without any modification. All EXPR
methods are marked for aggressive inlining to eliminate the overhead that would
be caused by the method call.
To keep the code really short, it's recommended to include the methods into the namespace, so they can be used without
the class name. To do so, simply add using static GriffinPlus.Lib.Expressions.LambdaExpressionInliners
at the
beginning of the C# source file where these methods are used.
The EXPR
methods are available for lambda expressions with up to 16 parameters and with/without return value:
// without return value (Action<>)
public static Expression<Action> EXPR(Expression<Action> expr);
public static Expression<Action<TIn1>> EXPR<TIn1>(Expression<Action<TIn1>> expr);
public static Expression<Action<TIn1, TIn2>> EXPR<TIn1, TIn2>(Expression<Action<TIn1, TIn2>> expr);
public static Expression<Action<TIn1, TIn2, TIn3>> EXPR<TIn1, TIn2, TIn3>(Expression<Action<TIn1, TIn2, TIn3>> expr);
public static Expression<Action<TIn1, TIn2, TIn3, TIn4>> EXPR<TIn1, TIn2, TIn3, TIn4>(Expression<Action<TIn1, TIn2, TIn3, TIn4>> expr);
public static Expression<Action<TIn1, TIn2, TIn3, TIn4, TIn5>> EXPR<TIn1, TIn2, TIn3, TIn4, TIn5>(Expression<Action<TIn1, TIn2, TIn3, TIn4, TIn5>> expr);
public static Expression<Action<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6>> EXPR<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6>(Expression<Action<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6>> expr);
public static Expression<Action<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7>> EXPR<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7>(Expression<Action<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7>> expr);
public static Expression<Action<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8>> EXPR<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8>(Expression<Action<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8>> expr);
public static Expression<Action<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9>> EXPR<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9>(Expression<Action<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9>> expr);
public static Expression<Action<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10>> EXPR<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10>(Expression<Action<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10>> expr);
public static Expression<Action<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11>> EXPR<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11>(Expression<Action<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11>> expr);
public static Expression<Action<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12>> EXPR<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12>(Expression<Action<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12>> expr);
public static Expression<Action<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13>> EXPR<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13>(Expression<Action<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13>> expr);
public static Expression<Action<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TIn14>> EXPR<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TIn14>(Expression<Action<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TIn14>> expr);
public static Expression<Action<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TIn14, TIn15>> EXPR<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TIn14, TIn15>(Expression<Action<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TIn14, TIn15>> expr);
public static Expression<Action<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TIn14, TIn15, TIn16>> EXPR<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TIn14, TIn15, TIn16>(Expression<Action<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TIn14, TIn15, TIn16>> expr);
// with return value (Func<>)
public static Expression<Func<TOut>> EXPR<TOut>(Expression<Func<TOut>> expr);
public static Expression<Func<TIn1, TOut>> EXPR<TIn1, TOut>(Expression<Func<TIn1, TOut>> expr);
public static Expression<Func<TIn1, TIn2, TOut>> EXPR<TIn1, TIn2, TOut>(Expression<Func<TIn1, TIn2, TOut>> expr);
public static Expression<Func<TIn1, TIn2, TIn3, TOut>> EXPR<TIn1, TIn2, TIn3, TOut>(Expression<Func<TIn1, TIn2, TIn3, TOut>> expr);
public static Expression<Func<TIn1, TIn2, TIn3, TIn4, TOut>> EXPR<TIn1, TIn2, TIn3, TIn4, TOut>(Expression<Func<TIn1, TIn2, TIn3, TIn4, TOut>> expr);
public static Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TOut>> EXPR<TIn1, TIn2, TIn3, TIn4, TIn5, TOut>(Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TOut>> expr);
public static Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TOut>> EXPR<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TOut>(Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TOut>> expr);
public static Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TOut>> EXPR<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TOut>(Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TOut>> expr);
public static Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TOut>> EXPR<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TOut>(Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TOut>> expr);
public static Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TOut>> EXPR<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TOut>(Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TOut>> expr);
public static Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TOut>> EXPR<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TOut>(Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TOut>> expr);
public static Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TOut>> EXPR<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TOut>(Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TOut>> expr);
public static Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TOut>> EXPR<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TOut>(Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TOut>> expr);
public static Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TOut>> EXPR<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TOut>(Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TOut>> expr);
public static Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TIn14, TOut>> EXPR<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TIn14, TOut>(Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TIn14, TOut>> expr);
public static Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TIn14, TIn15, TOut>> EXPR<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TIn14, TIn15, TOut>(Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TIn14, TIn15, TOut>> expr);
public static Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TIn14, TIn15, TIn16, TOut>> EXPR<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TIn14, TIn15, TIn16, TOut>(Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TIn14, TIn15, TIn16, TOut>> expr);
In order to initialize an array of expressions you will usually have to write something like this:
Expression<Func<int,int,int>> add = (x,y) => x + y;
Expression<Func<int,int,int>> subtract = (x,y) => x - y;
Expression<Func<int,int,int>> multiply = (x,y) => x * y;
Expression<Func<int,int,int>> divide = (x,y) => x / y;
var expressions = new[] { add, subtract, multiply, divide };
Each and every expression must be assigned to a named variable. This can become cumbersome when juggling with many expressions.
With the EXPR<>
methods you can avoid inventing temporary variable names by inlining the expressions:
var expressions = new[]
{
EXPR<int,int,int>((x,y) => x + y),
EXPR<int,int,int>((x,y) => x - y),
EXPR<int,int,int>((x,y) => x * y),
EXPR<int,int,int>((x,y) => x / y)
};
In mathematics, function composition is an operation that takes two functions f and g and produces a function h such that h(x) = g(f(x)). In this operation, the function g is applied to the result of applying the function f to x. That is, the functions f : X → Y and g : Y → Z are composed to yield a function that maps x in X to g(f(x)) in Z.
Transferred to lambda expressions this means that composing Expression<Func<X,Y>>
and Expression<Func<Y,Z>>
produces
Expression<Func<X,Z>>
. The LambdaExpressionComposeExtensions
class contains extension methods that extend strong-typed
lambda expressions with function composition features. Lambda composition is supported for up to 16 parameters using
the following extension methods:
public static Expression<Func<TOut>> Compose<TInterstitial, TOut>(this Expression<Func<TInterstitial>> inner, Expression<Func<TInterstitial, TOut>> outer);
public static Expression<Func<TIn1, TOut>> Compose<TIn1, TInterstitial, TOut>(this Expression<Func<In1, TInterstitial>> inner, Expression<Func<TInterstitial, TOut>> outer);
public static Expression<Func<TIn1, TIn2, TOut>> Compose<TIn1, TInterstitial, TOut>(this Expression<Func<TIn1, TIn2, TInterstitial>> inner, Expression<Func<TInterstitial, TOut>> outer);
public static Expression<Func<TIn1, TIn2, TIn3, TOut>> Compose<TIn1, TIn2, TInterstitial, TOut>(this Expression<Func<TIn1, TIn2, TIn3, TInterstitial>> inner, Expression<Func<TInterstitial, TOut>> outer);
public static Expression<Func<TIn1, TIn2, TIn3, TIn4, TOut>> Compose<TIn1, TIn2, TIn3, TInterstitial, TOut>(this Expression<Func<TIn1, TIn2, TIn3, TIn4, TInterstitial>> inner, Expression<Func<TInterstitial, TOut>> outer);
public static Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TOut>> Compose<TIn1, TIn2, TIn3, TIn4, TInterstitial, TOut>(this Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TInterstitial>> inner, Expression<Func<TInterstitial, TOut>> outer);
public static Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TOut>> Compose<TIn1, TIn2, TIn3, TIn4, TIn5, TInterstitial, TOut>(this Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TInterstitial>> inner, Expression<Func<TInterstitial, TOut>> outer);
public static Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TOut>> Compose<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TInterstitial, TOut>(this Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TInterstitial>> inner, Expression<Func<TInterstitial, TOut>> outer);
public static Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TOut>> Compose<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TInterstitial, TOut>(this Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TInterstitial>> inner, Expression<Func<TInterstitial, TOut>> outer);
public static Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TOut>> Compose<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TInterstitial, TOut>(this Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TInterstitial>> inner, Expression<Func<TInterstitial, TOut>> outer);
public static Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TOut>> Compose<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TInterstitial, TOut>(this Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TInterstitial>> inner, Expression<Func<TInterstitial, TOut>> outer);
public static Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TOut>> Compose<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TInterstitial, TOut>(this Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TInterstitial>> inner, Expression<Func<TInterstitial, TOut>> outer);
public static Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TOut>> Compose<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TInterstitial, TOut>(this Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TInterstitial>> inner, Expression<Func<TInterstitial, TOut>> outer);
public static Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TOut>> Compose<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TInterstitial, TOut>(this Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TInterstitial>> inner, Expression<Func<TInterstitial, TOut>> outer);
public static Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TIn14, TOut>> Compose<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TIn14, TInterstitial, TOut>(this Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TIn14, TInterstitial>> inner, Expression<Func<TInterstitial, TOut>> outer);
public static Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TIn14, TIn15, TOut>> Compose<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TIn14, TIn15, TInterstitial, TOut>(this Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TIn14, TIn15, TInterstitial>> inner, Expression<Func<TInterstitial, TOut>> outer);
public static Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TIn14, TIn15, TIn16, TOut>> Compose<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TIn14, TIn15, TIn16, TInterstitial, TOut>(this Expression<Func<TIn1, TIn2, TIn3, TIn4, TIn5, TIn6, TIn7, TIn8, TIn9, TIn10, TIn11, TIn12, TIn13, TIn14, TIn15, TIn16, TInterstitial>> inner, Expression<Func<TInterstitial, TOut>> outer);
Expression<Func<int,int,double>> expr1 = (x,y) => 5.0 * (x + y);
Expression<Func<double,string>> expr2 = (x) => x.ToString();
Expression<Func<int,int,string>> composition = expr1.Compose(expr2); // same as: (x,y) => (5.0 * (x + y)).ToString();
The library provides the ExpressionEqualityComparer
class to calculate hash codes for expressions and check them for
equality. This class implements the System.Collections.Generic.IEqualityComparer<Expression>
interface and can
therefore be used in conjunction with common collections as usual. It is recommended to use its singleton property
Instance
to reduce GC pressure. The instance uses thread-local storage and is therefore thread-safe.
Expression<Func<int,int,double>> expr1 = (x,y) => 5.0 * (x + y);
Expression<Func<int,int,double>> expr2 = (x,y) => 5.0 * (x + y);
int hashCode1 = ExpressionEqualityComparer.Instance.GetHashCode(expr1); // 0x497c66b1
int hashCode2 = ExpressionEqualityComparer.Instance.GetHashCode(expr2); // 0x497c66b1
bool isEqual = ExpressionEqualityComparer.Instance.Equals(expr1, expr2); // true