Expression.Condition: 参数类型不匹配

Expression.Condition: Argument types do not match

我正在尝试使用表达式来创建这个:

bool.Parse("true") ? default(int?) : 1

顺便说一句,我使用 bool.Parse("true") 只是为了防止 VS 抱怨无法访问的代码路径,所以假设它使用常量 true。当我这样写我的表情时...

Expression.Condition(Expression.Constant(true), Expression.Default(typeof(int?)),
    Expression.Constant(1))

...我收到错误 Argument types do not match。我很确定我知道发生了什么,所以我改变了我的表情来做到这一点:

Expression.Condition(Expression.Constant(true), Expression.Default(typeof(int?)),
    Expression.New(typeof(int?).GetConstructor(new[] { typeof(int) }), Expression.Constant(1)));

它有效,但我不能说我喜欢写一个与此等效的表达式:

bool.Parse("true") ? default(int?) : new int?(1)

有没有办法在不创建 int? 的新实例的情况下使这个三元表达式起作用?也许这样做是可以的,因为 c# 无论如何都会在我的具体示例中隐式创建一个新实例?

编辑

我应该注意,我只使用 Expression.Constant()MethodCallExpression 模拟 return 值,以简化我的代码示例。因此,任何建议使用常量值作为解决方案的建议在这种情况下都不起作用。

您可以使用 new 创建一个转换而不是创建一个实例,即

bool.Parse("true") ? default(int?) : (int?)(1)

像这样:

Expression.Condition(
    Expression.Constant(true)
,   Expression.Default(typeof(int?))
,   Expression.Convert(Expression.Constant(1), typeof(int?))
)

Demo.

当你写 bool.Parse("true") ? default(int?) : 1 它实际上被编译成更类似于的东西:

bool.Parse("true") ? default(int?) : new int?(1)

那么为什么不直接使用值为 1 的常量 int?,就像这样:

Expression.Condition(Expression.Constant(true), 
    Expression.Default(typeof(int?)), 
    Expression.Constant(1, typeof(int?)))

Expression.Constant 的重载必须用作传递 int? 作为 object 将框住基础 int 或传递 null,你必须明确说明它是一个 int? 常量。

键入常量表达式:

Expression.Condition(Expression.Constant(true), 
  Expression.Default(typeof(int?)), 
  Expression.Constant(1, typeof(int?)))

或输入条件表达式:

Expression.Condition(Expression.Constant(true), 
  Expression.Default(typeof(int?)), 
  Expression.Constant(1),
  typeof(int?))

第一个改变常量的工作方式(在这两种情况下,值都存储为装箱的 int,就像 int 常量一样,如果需要,取消装箱,是 int?.

第二个使条件本身存储两个操作数必须转换为的类型。

请注意,可能没有任何实际演员表,尤其是前两个,例如如果你编译你可能会编译成直接作用于 int? 的形式,所以虽然表达式对象需要强制转换才能作用,但它生成的编译代码不需要。

另请注意,某些提供程序无法处理类型化条件,因此最后一个选项不可用。例如。 EnumerableQuery 无法对付它们(参见 https://github.com/dotnet/corefx/issues/3607)。