【问题标题】:IEnumerable<T>: Can use Equals method but not equality operatorIEnumerable<T>:可以使用 Equals 方法但不能使用相等运算符
【发布时间】:2022-01-15 14:54:38
【问题描述】:
    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)

!给你一个错误提示

运算符“!”不能应用于“T”类型的操作数

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

运算符“==”不能应用于“T”和“T”类型的操作数

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

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

【问题讨论】:

  • 您在寻找什么样的“为什么”?这就是语言的设计方式?您会对语言规范中的引用感到满意吗?另见:meta.stackoverflow.com/questions/293815/…
  • 我对下面的答案很满意。在这个阶段,我只是在学习语言的所有部分是如何组合在一起的,所以我的“为什么”问题可能很容易回答。
  • 在这种情况下,您应该考虑通过单击该复选标记来接受答案:)

标签: c# generics ienumerable equality-operator


【解决方案1】:

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

【讨论】:

  • 所以我认为相等运算符在全球范围内可用,实际上它必须为每个特定类型实现。在这种情况下,您不能为实际上不是类型的类型 (T) 实现运算符是有道理的。
  • 感谢您的回答
【解决方案2】:

请参阅指定== 的语言规范的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 类型的值使用 Equals,即使 T 可以是任何类型。

【讨论】:

  • 谢谢,真的很有帮助。我会将您的答案标记为已接受,只是因为它更详细一些。两者都很有帮助。
【解决方案3】:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-21
    • 2013-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-19
    相关资源
    最近更新 更多