This test:
[Fact]
public void X()
{
Assert.IsType<Expression<Func<int>>>(Expression.Lambda<Func<int>>(Expression.Constant(1)));
}
Runs on .NET Framework, but fails on .NET Core (3.1 in my case) with the following error:
Expected: System.Linq.Expressions.Expression`1[[System.Func`1[[System.Int32, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]
Actual: System.Linq.Expressions.Expression0`1[[System.Func`1[[System.Int32, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]
Why is this? And can I do something to compare the types properly?
Incorrect version of my answer before:
Assuming the behavior for .Net Core is the same or similar to framework, here is my reasoning.
Looking at the reference source code
Expression.Lambda<T>
creates a runtime type ofExpression<T>
, seetypeof(Expression<>).MakeGenericType
.
typeof(Expression<T>)
however is the compile time type.
Using the following LINQPad script you see the difference in the output
var exp = Expression.Lambda<Func<Int32>>(Expression.Constant(1));
exp.GetType().BaseType.Dump();
// System.Linq.Expressions.Expression`1[System.Func`1[System.Int32]]
typeof(Expression<Func<Int32>>).BaseType.Dump();
// System.Linq.Expressions.LambdaExpression
For .Net Framework an instance of Expression<T> is returned from Expression.Lambda<T>(Expression exp)
as expected.
But for .Net Core the behavior was changed!
For .Net Core either Expression<TDelegate>.Create or ExpressionCreator<TDelegate>.CreateExpressionFunc is called along the way but in both cases - for this example here - a new instance of Expression0{T} : Expression{T}
is returned! Which are obviously not of the same type.
var expression = Expression.Lambda<Func<int>>(Expression.Constant(1));
// extract the type of used generics
var genericArgs = expression.GetType().GetGenericArguments();
// TODO: assert that we DO have exactly one argument here
Assert.IsType<Func<int>>(genericArgs[0]);
// another assert:
// unverified, but `(expression is Expression<Func<int>> _).Dump();` returns `true` in LINQPad
Assert.True(expression is Expression<Func<int>>);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With