IEnumerable<T>:可以使用 Equals 方法但不能使用相等运算符

IEnumerable<T>: Can use Equals method but not equality operator

    public static IEnumerable<T> Method<T>(IEnumerable<T> iterable){

    T previous = default(T);
    foreach(T current in iterable){

        if (!current.Equals(previous)){

            previous = current;
            yield return current;
        }
    }
}

我对这段代码没有任何疑问,但为什么可以使用以下方法比较两个类型 T 的对象:

if (!current.Equals(previous))

那为什么不能比较使用:

if (!current == previous)

!给你一个错误说

Operator '!' cannot be applied to operand of type 'T'

如果你删除它,你会得到:

Operator '==' cannot be applied to operands of type 'T' and 'T'

我放弃了一个代码挑战,因为它似乎在告诉我你真的无法将一个 T 与另一个进行比较。然后我发现你可以做到这一点,但只需使用不同的 syntax/using 特定方法。

谁能告诉我为什么会这样?

.EqualsSystem.Object 的一部分。现在没有办法限制泛型支持特定的运算符重载。但是,您可以使用 IEquatable<T>IEqualityComparer<T> 来确保类型实现其相等性定义。

请参阅语言规范的 this section,其中指定了 ==。您可以看到该语言仅预定义了 == 这些重载:

bool operator ==(int x, int y);
bool operator ==(uint x, uint y);
bool operator ==(long x, long y);
bool operator ==(ulong x, ulong y);
bool operator ==(float x, float y);
bool operator ==(double x, double y);
bool operator ==(decimal x, decimal y);
bool operator ==(bool x, bool y);
bool operator ==(E x, E y); // for every enum E
bool operator ==(C x, C y); // for every class C
bool operator ==(string x, string y);
bool operator ==(System.Delegate x, System.Delegate y);

你的方法中的类型参数 T 没有任何限制,那么如果它是一个结构类型呢?从上面的列表中可以看出,没有为任意结构类型定义 == 运算符。

如果添加 T: class 约束,则可以对其使用 ==,因为所有 类 都有一个 == 运算符。

另一方面,在 System.Object 中声明了一个 Equals 方法,C# 中的每个类型都继承自该方法。因此,即使 T 可以是任何类型,也可以对 T 类型的值使用 Equals

请注意,如果对象是原始值类型、字符串或定义了 operator == 的用户结构,则 == 只能表示值相等。

在所有其他情况下,== 未定义(值类型)或引用 object.ReferenceEquals() 检查两个变量是否引用内存中的同一对象。

请注意,新的 record 类型支持具有值语义的 == 运算符,即使它们是引用类型。这是因为他们在幕后实施 IEquatable<T> 并定义 operator == 以使用 .Equals().