为什么将单个元素与 IEnumerable 进行比较不是编译错误

本文关键字:比较 编译 错误 单个 元素 IEnumerable 为什么 | 更新日期: 2023-09-27 17:50:53

var fooRef = new FooRef();
var fooRefEnumerable = Enumerable.Empty<FooRef>();
var fooRefEquality = (fooRef == fooRefEnumerable); //This compiles without any errors
var fooVal = new FooVal();
var fooValEnumerable = Enumerable.Empty<FooVal>();
//Compilation error : Error 1 Operator '==' cannot be applied to operands of type 'FooVal' and 'System.Collections.Generic.IEnumerable<FooVal>'
var fooValEquality = (fooVal == fooValEnumerable); 
public class FooRef { }
public struct FooVal { }   

为什么要比较单个对象和对 RefType 有效的 IEnumerable?

为什么将单个元素与 IEnumerable 进行比较不是编译错误

为什么比较单个对象和 IEnumerable 对 RefType 有效?

因为它完全有可能返回true

class CunningFooRef : FooRef, IEnumerable<FooRef>
{
    // Implementation...
}
FooRef fooRef = new CunningFooRef();
IEnumerable<FooRef> fooRefEnumerable = Enumerable.Empty<FooRef>();
Console.WriteLine(fooRef == fooRefEnumerable); // False
fooRefEnumerable = (IEnumerable<FooRef>) fooRef;
Console.WriteLine(fooRef == fooRefEnumerable); // True

请注意,这对fooReffooRefEnumerable使用的编译时类型与您使用的编译时类型相同。

如果您密封FooRef,以便编译器知道FooRef引用不可能也是IEnumerable<FooRef>引用,那么您将收到编译时错误。

你这样做的原因是因为fooVal(你的结构(与fooValEnumerable(IEnumerable类型(的类型不同。结构是值类型,您无法将其与此类引用类型进行比较。

== 标记用于表示两个不同的运算符,在某些语言(如 VB(中,这两个运算符使用不同的标记表示。 如果任一操作数类型具有适用于另一种类型的已定义重载,则==将表示可重载的相等运算符并使用该重载。 否则,如果两个操作数都是引用类型,并且它们可以标识相同的(非 null(对象,它将表示引用相等运算符。 请注意,引用相等性测试的语义对于任何类型的任何组合都有很好的定义;如果X识别苹果,Y识别橙子,"X和Y识别同一个物体"这个问题可以毫无困难地回答(总是"否"(。 C#会拒绝一些这样的比较,因为试图比较试图提出答案总是"否"的问题的事物很容易是一个错误,但如果例如X是未密封的类Automotive,Y是IFloatable,编译器将允许X和Y可能同时识别相同的两栖车辆(它派生自Automotive并实现IFloatable。 请注意,如果X是一个密封的类[或一个结构,它必然是密封的],编译器将认识到,如果X的类没有实现IFloatable,X就无法识别一个对象。