为什么Nullable< T>不重载==运算符? [英] Why Nullable<T> doesn't overload == opertator?

查看:68
本文介绍了为什么Nullable< T>不重载==运算符?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  Nullable< Int32>x = 5;Nullable< Int32>y = 10;如果(x == y){...} 

根据我的理解,上面的代码会将 x y 都强制转换为 Object ,然后使用 Object 公共静态布尔Equals(Object objA,Object objB)方法

如果我的理解是正确的,那么为什么不将 Nullable< T> 的==和!=运算符重载为:

 公共结构Nullable< T>其中T:struct {...公共静态布尔运算符==(Nullable T a,Nullable T b){...//做一些必要的空检查返回值.等于(其他);}} 

那我们可以省下两个铸件吗?

解决方案

可为空的值类型上的运算符实际上是硬编码"的.在语言规范中.它们被称为提升运算符.

提升的运算符允许对非空值类型进行操作的预定义和用户定义的运算符也可以与这些类型的可空形式一起使用.

对于相等运算符,

通过向每个操作数类型添加单个?修饰符来构造提升形式.提升运算符认为两个空值相等,并且一个空值不等于任何非空值.如果两个操作数都不为空,则提升操作符将取消包装操作数并应用基础操作符以产生布尔结果.

这是在语言规范中指定的,因此运算符都由"compiler magic"实现,这就是为什么您没有在 Nullable 结构中看到声明的原因.

编译器魔术的确切作用是实现细节,但是我很确定它不会在这里对 object 进行强制转换,因为您使用的是 ==的提升形式.(int,int).根据规范,如果两个操作数都不为null,而不是 object.Equals .这将应用 ==(int,int)(基础运算符")./p>

nollow nollow

 公共布尔F(int?a,int?b){返回a == b;} 

收件人:

 公共布尔值F(Nullable  a,Nullable  b){Nullable< int>num = a;Nullable< int>num2 = b;return(num.GetValueOrDefault()== num2.GetValueOrDefault())&(num.HasValue == num2.HasValue);} 

一个通用的实现是:

 公共静态布尔运算符==(Nullable T a,Nullable T b){return(a.GetValueOrDefault()== b.GetValueOrDefault())&&(a.HasValue == b.HasValue);} 

但是请注意,以上内容不会在普通C#中编译,因为不能保证在 T 上定义 == .但是,由于提升形式 ==(T ?, T?)且仅当 ==(T,T)存在的情况下存在,而且由于这是由编译器魔术实现的,所以很好.

Nullable<Int32> x = 5;
Nullable<Int32> y = 10;

if (x == y) {
   ...
}

From my understanding, the code above will cast both x and y to Object and then use Object's public static bool Equals(Object objA, Object objB) method

if my understanding is correct, then why not overload == and != operator for Nullable<T> as:

public struct Nullable<T> where T : struct {
   ...
   public static bool operator == (Nullable<T> a, Nullable<T> b) {
      ...// do some nesseary null check
      return value.Equals(other);
   }
}

then we can save two castings?

解决方案

Operators on nullable value types are actually "hardcoded" in the language spec. They are known as Lifted Operators.

Lifted operators permit predefined and user-defined operators that operate on non-nullable value types to also be used with nullable forms of those types.

For the equality operators,

The lifted form is constructed by adding a single ? modifier to each operand type. The lifted operator considers two null values equal, and a null value unequal to any non-null value. If both operands are non-null, the lifted operator unwraps the operands and applies the underlying operator to produce the bool result.

This is specified in the language spec so the operators are all implemented by "compiler magic", which is why you don't see a declaration in the Nullable struct.

Exactly what the compiler magic does is implementation detail, but I'm pretty sure it wouldn't do a cast to object here, because you are using the lifted form of ==(int, int). According to the spec, this would apply ==(int, int) ("the underlying operator") if both operands are not null, not object.Equals.

On sharplab.io, you can see that that version of the compiler compiles this:

public bool F(int? a, int? b) {
    return a == b;
}

to:

public bool F(Nullable<int> a, Nullable<int> b)
{
    Nullable<int> num = a;
    Nullable<int> num2 = b;
    return (num.GetValueOrDefault() == num2.GetValueOrDefault()) & (num.HasValue == num2.HasValue);
}

A generic implementation of this would be:

public static bool operator == (Nullable<T> a, Nullable<T> b) {
    return (a.GetValueOrDefault() == b.GetValueOrDefault()) && (a.HasValue == b.HasValue);
}

But note that the above is not going to compile in normal C#, because == is not guaranteed to be defined on T. However, since the lifted form ==(T?, T?) exists if and only if ==(T, T) exists, and because this is implemented by compiler magic, we're fine.

这篇关于为什么Nullable&lt; T&gt;不重载==运算符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆