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?))
)
当你写 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)。
我正在尝试使用表达式来创建这个:
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?))
)
当你写 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)。