.NET Core 和类型相等

asg*_*las 5 .net-core

本次测试:

[Fact]
public void X()
{
    Assert.IsType<Expression<Func<int>>>(Expression.Lambda<Func<int>>(Expression.Constant(1)));
}
Run Code Online (Sandbox Code Playgroud)

在 .NET Framework 上运行,但在 .NET Core(在我的情况下为 3.1)上失败并出现以下错误:

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]]
Run Code Online (Sandbox Code Playgroud)

为什么是这样?我可以做些什么来正确比较类型吗?

cke*_*rth 3

我之前的答案的错误版本:

假设 .Net Core 的行为与框架相同或相似,这是我的推理。

查看参考源代码 Expression.Lambda<T>会创建一个运行时类型Expression<T>,请参阅typeof(Expression<>).MakeGenericType

typeof(Expression<T>)然而是编译时类型。

使用以下 LINQPad 脚本,您会看到输出中的差异

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
Run Code Online (Sandbox Code Playgroud)

对于 .Net Framework,按预期返回Expression<T>的实例。Expression.Lambda<T>(Expression exp)

但对于.Net Core,行为发生了变化!

对于 .Net Core,Expression<TDelegate>.CreateExpressionCreator<TDelegate>.CreateExpressionFunc都会被调用,但在这两种情况下 - 对于这里的示例 -Expression0{T} : Expression{T}返回一个新实例!这显然不是同一类型。

断言你可以使用的类型

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>>);
Run Code Online (Sandbox Code Playgroud)