C# 未为类型';System.Int32';和';System.Object';
我要构建以下表达式:C# 未为类型';System.Int32';和';System.Object';,c#,.net,expression,C#,.net,Expression,我要构建以下表达式: myObj.Id == null myObj.Id是一个不可为null的int。我知道,如果按字面计算此表达式,则结果将始终为false,但我需要构建此表达式,因为表达式访问者稍后将对其进行检查并对其进行处理 完全可以在代码中直接编写此表达式,但当我尝试使用以下工厂方法动态构建它时: Expression.Equal(left: /* myObj.Id */, right: /* anotherId */); 我得到以下例外情况: 未为类型“System.Int32”和
myObj.Id == null
myObj.Id
是一个不可为null的int。我知道,如果按字面计算此表达式,则结果将始终为false,但我需要构建此表达式,因为表达式访问者稍后将对其进行检查并对其进行处理
完全可以在代码中直接编写此表达式,但当我尝试使用以下工厂方法动态构建它时:
Expression.Equal(left: /* myObj.Id */, right: /* anotherId */);
我得到以下例外情况:
未为类型“System.Int32”和“System.Object”定义二进制运算符Equal
这是没有意义的,因为可以用C#逐字写出完全相同的表达式
如何生成该表达式<代码>==null
如何生成该表达式?==空的
编译器将int
升级为可空类型,即null
,也称为int?
。你也需要这样做
作为一种通用技术,使用编译器本身向您展示如何构建一个满足您需要的表达式
对象通常很有帮助。例如,要回答您的特定问题,即如何生成该表达式,只需编写所需的表达式,编译它,然后在调试器中运行它,这样您就可以查看编译器执行了什么操作:
表达式ex=i=>i==null;
如果这样做,您将发现一个表达式的主体值为“(Convert(i)==null)”
。也就是说,节点类型为Equal
,右操作数为null
,左操作数为Convert
节点,其操作数为int
值i
,目标类型为null
有了这些信息,现在编写实际构建该表达式的C#代码应该相对容易了。当然,另一种方法是只使用上面的声明(或类似的声明),并始终让编译器为您构建表达式
对象。我个人不喜欢写表达式
——如果我能帮上忙的话。它非常冗长而且容易出错,所以任何时候编译器都可以为我做这项工作(这是非常常见的),我就让它来做。@HansPassant我在你的评论后编辑了这个问题,你能再看一遍吗?我想构建==null
。我尝试将liftToNull
参数设置为true,但没有解决问题。“这没有意义,因为可以按字面意思编写相同的表达式”——如何?您的示例中的另一个是什么?如果它不是对象
类型的东西,那么它与您的需求有什么关系?如果它是object
类型的东西,是什么让你说,例如表达式i==o
其中i
是int
,而o
是object将被编译?不会的。为了表达式的目的,您可能希望从值类型强制转换为可空类型(例如nullable
或装箱的int
),但是如果没有更多的上下文,就不可能知道您需要什么。这让人怀疑它像一个。值得一提的是,当您试图学习如何使用表达式API时,首先让编译器为您构建表达式通常是有帮助的。例如,编译并执行以下代码:Expression ex=i=>i==null
。然后进入调试器并检查ex
的值,以查看编译器做了什么。然后你就做同样的事情。提示:编译器将int
提升为Nullable
akaint?