C# 可空相等操作,为什么 null <= null 解析为 false?

标签 c# .net null comparison-operators

<分区>

为什么是.NET

null >= null

解析为假,但是

null == null 

解析为真?

换句话说,为什么 null >= null 不等同于 null > null || null == null?

有官方的答案吗?

最佳答案

此行为在 C# 规范 ( ECMA-334 ) 的第 14.2.7 节中定义(我已突出显示相关部分):

For the relational operators

< > <= >=

a lifted form of an operator exists if the operand types are both non-nullable value types and if the result type is bool. The lifted form is constructed by adding a single ? modifier to each operand type. The lifted operator produces the value false if one or both operands are null. Otherwise, the lifted operator unwraps the operands and applies the underlying operator to produce the bool result.

特别是,这意味着通常的关系法则不成立; x >= y并不意味着 !(x < y) .

血淋淋的细节

有些人问为什么编译器认为这是 int? 的提升运算符首先。我们来看一下。 :)

我们从 14.2.4“二元运算符重载决议”开始。这详细说明了要遵循的步骤。

  1. 首先,检查用户定义的运算符的适用性。这是通过检查由 >= 的每一侧的类型定义的运算符来完成的。 ...这提出了一个问题,即 null 的类型是什么?是! null在给定一个之前,文字实际上没有任何类型,它只是“空文字”。按照 14.2.5 下的说明,我们发现这里没有合适的运算符,因为 null 文字没有定义任何运算符。

  2. 此步骤指示我们检查预定义运算符集的适用性。 (本节也排除了枚举,因为两边都不是枚举类型。)相关的预定义运算符在 14.9.1 到 14.9.3 节中列出,它们都是原始数字类型的运算符,以及提升版本这些运算符(注意此处不包括 string s 运算符)。

  3. 最后,我们必须使用这些运算符和 14.4.2 中的规则执行重载决议。

实际上执行这个决议会非常乏味,但幸运的是有一个捷径。在 14.2.6 下有一个重载决议结果的信息示例,其中指出:

...consider the predefined implementations of the binary * operator:

int operator *(int x, int y);
uint operator *(uint x, uint y);
long operator *(long x, long y);
ulong operator *(ulong x, ulong y);
void operator *(long x, ulong y);
void operator *(ulong x, long y);
float operator *(float x, float y);
double operator *(double x, double y);
decimal operator *(decimal x, decimal y);

When overload resolution rules (§14.4.2) are applied to this set of operators, the effect is to select the first of the operators for which implicit conversions exist from the operand types.

由于两边都是null我们可以立即丢弃所有未解除的运算符。这给我们留下了所有原始数字类型的提升数字运算符。

然后,使用先前的信息,我们选择第一个存在隐式转换的运算符。由于 null 文字可隐式转换为可空类型,并且 int 存在可空类型,我们从列表中选择第一个运算符,即 int? >= int? .

关于C# 可空相等操作,为什么 null <= null 解析为 false?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43121625/

相关文章:

c# 组合框绑定(bind)和第一个空值

c# - 组合框事件 SelectedValueChanged

.net - 基于POCO的多层.NET框架

c# - 从事件中获取事件处理程序?

null - mysqldump 将 null 存储为空白

c# - 如何将 "NULL/DbNull"发送到数据类型为 : nullable int 的表列中

c# - Entity Framework 修改集合属性并关闭检测更改

c# - MySQL在线数据库

c# - 将图像写入 SQL Server CE

c# - 模块化 C# Compact Framework 2.0 应用程序