为什么不使用==操作符(为具体类型定义)

本文关键字:类型 定义 操作符 为什么不 | 更新日期: 2023-09-27 17:53:05

我有一个列表定义为:

var Items = new List<IItem>();

现在有许多不同的类具有该接口,其中一个是Consumable。Consumable类也重载了==操作符。现在我有以下代码,不能工作:

if(item1 == item2)
{
    //code...
}

这不起作用。我在==操作符重载中设置了一个断点,它永远不会到达它。当我逐行调试时,item1和item2的类型都是Consumable, GetType都返回Consumable。我甚至尝试了下面的代码:

var temp = item1.GetType();
var temp2 = item2.GetType();
if (temp == temp2)
{
    //code...
}

,这个等式的结果为真。现在,如果我试一下:

if(((Consumable)item1) == ((Consumable)item2))
{
    //code...
}

,这会触发==操作符重载中的断点。为什么我必须手动转换变量,如果逐行调试显示它已经认为它们都是可消费的?是因为我从iitem列表中提取它们吗?

为什么不使用==操作符(为具体类型定义)

由于您的列表是List<IItem>,我假设您有如下内容:

var item1 = Items[0];

之类的;这里item1 变量的类型为IItem。操作符解析在构建过程中通过静态分析进行(而不是在运行时通过多态性/RTTI),因此唯一可用的==是任何object的默认值,即引用相等。

为了支持您的自定义操作符,变量必须相应地键入,例如:

Consumable item1 = ..., item2 = ...;

你的cast达到了类似的效果。

另一个选择是确保==Equals(和GetHashCode())一致,并使用:

if(Equals(item1, item2)) {...}

将执行null检查,然后使用覆盖的Equals方法。这样就支持多态,所以类型是什么并不重要。

公共语言运行时只知道您的两个对象实现接口IItem。对象层次结构中最小的公共部分是System.Object。您没有重载System.Object的==操作符。

要使用正确的重载,必须声明对象的类型。

==不检查类型是否相等,但对于类,它检查引用是否相等。所以如果两个变量都指向同一个对象,它就为真。例如:

var temp = item1;
var temp2 = item1;
if( temp == temp2 )
{
  //this code will execute
}

IItem不应该具有可比性吗?