【问题标题】:The binary operator Equal is not defined for the types 'System.Int32' and 'System.Object'没有为类型“System.Int32”和“System.Object”定义二元运算符 Equal
【发布时间】:2020-09-28 22:11:26
【问题描述】:

我想构建以下表达式:

myObj.Id == null

myObj.Id 是一个不可为空的 int。我知道如果这个表达式是按字面计算的,那么结果总是错误的,但我需要构建这个表达式,因为表达式访问者稍后会检查它并用它做一些事情。

完全可以在您的代码中逐字编写此表达式,但是当我尝试使用以下工厂方法动态构建它时:

Expression.Equal(left: /* myObj.Id */, right: /* anotherId */);

我得到以下异常:

没有为类型“System.Int32”和“System.Object”定义二元运算符 Equal。

这没有意义,因为在 C# 中可以写出完全相同的表达式。

如何生成该表达式? <int> == null?

【问题讨论】:

  • @HansPassant 我在您发表评论后编辑了问题,您能再看一下吗?我想建立<int> == null。我尝试将liftToNull 参数设置为true,但并没有解决问题。
  • “这没有意义,因为可以按字面意思写出完全相同的表达式” -- 怎么样?在您的示例中,anotherId 是什么?如果它不是object 类型的东西,那与您的需求有什么关系?如果它是object 类型的东西,是什么让你这么说,例如表达式i == o 其中iinto 是对象会编译吗?它不会。 也许出于表达式的目的,您想要从值类型转换为可空类型(例如Nullable<T> 或装箱int),但没有更多上下文,不可能知道你需要什么
  • 这感觉有点像XY problem
  • 不管怎样,当您尝试学习如何使用表达式 API 时,首先让编译器为您构建表达式通常会很有帮助。例如,编译并执行这段代码:Expression<Func<int, bool>> ex = i => i == null。然后进入调试器并检查ex 的值,看看编译器做了什么。然后你就做同样的事情。提示:编译器将int 提升为Nullable<int> aka int?

标签: c# .net expression


【解决方案1】:

如何生成该表达式? == 空?

编译器将int 提升为可空类型,即Nullable<int>,也称为int?。你也需要这样做。

作为一种通用技术,使用编译器本身向您展示如何构建一个满足您需求的Expression 对象通常很有帮助。例如,要回答您的具体问题,如何生成该表达式,只需编写您想要的表达式,编译它,然后在调试器中运行它,这样您就可以查看编译器做了什么:

Expression<Func<int, bool>> ex = i => i == null;

如果你这样做,你会发现一个表达式的Body 值为"(Convert(i) == null)"。即节点类型为Equal,右操作数为null,左操作数为Convert节点,其操作数为inti,其目的类型为是Nullable&lt;int&gt;

有了这些信息,现在编写将实际构建该表达式的 C# 代码应该相对容易。当然,另一种方法是只使用上面的声明(或类似的东西)并且总是让编译器为您构建Expression 对象。如果我能提供帮助,我个人宁愿不写Expression-building 代码。它非常冗长且容易出错,所以任何时候编译器可以为我完成工作(这是很常见的),我让它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-11
    • 1970-01-01
    相关资源
    最近更新 更多