Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是可为空的<;T>;。Equals方法实现错误?_C#_Oop - Fatal编程技术网

C# 是可为空的<;T>;。Equals方法实现错误?

C# 是可为空的<;T>;。Equals方法实现错误?,c#,oop,C#,Oop,我这里说的是C语言 is中Object.Equals(Object)方法的定义: 确定指定的 对象等于当前对象 如果两个对象相等,则返回true;如果为null,则返回false: x、 等于(空引用)(在 visualbasic返回false 为什么??因为null不是一个对象 如果对象参数为null,则引发NullReferenceException 我们还有: x、 Equals(y)返回的值与 y、 等于(x) 在这里之前没问题。它与Java非常相似。但是C#还为不可为空的类型提供了一个

我这里说的是C语言

is中Object.Equals(Object)方法的定义:

确定指定的 对象等于当前对象

如果两个对象相等,则返回true;如果为null,则返回false:

x、 等于(空引用)(在 visualbasic返回false

为什么??因为null不是一个对象

如果对象参数为null,则引发NullReferenceException

我们还有:

x、 Equals(y)返回的值与 y、 等于(x)

在这里之前没问题。它与Java非常相似。但是C#还为不可为空的类型提供了一个
System.Nullable
struct。据我所知,结构是一个对象。它继承Object.Equals方法

如果我有这样一个结构:

struct Car
    {
        public string Make;
        public string Model;
        public uint Year;

        public Car(string make, string model, uint year)
        {
            Make = make;
            Model = model;
            Year = year;
        }
    }
并创建四个实例:

Car car1 = new Car("make", "model", 2009);
Car car2 = new Car("make", "model", 2009);
Car car3 = new Car("make", "model", 2008);

car1.Equals(car2); // will return true
car1.Equals(car3); // will return false;
据我所知,我们不能将结构设置为空值。但是System.Nullable是一个结构,我们可以编译它而不会出现任何错误:

int? i = null;
(我希望有人也能解释一下。它是结构还是其他东西?)

我真正的问题是:

i.Equals(null); // returns true!
(通常x.Equals(y)=y.Equals(x)当然为空。Equals(i)在这里无效…)


显然,Object.Equals方法在这里被重写。可能是有文件记录的,这是规定的。但是这种方法正确/好吗?如果是这样的话,可为空值的==和Equals方法之间的区别是什么?

我认为您的困惑源于以下几行

i? = null;
这实际上并不创建空值变量。它本质上是合成糖,用于以下用途

Nullable<int> i = new Nullable<int>();
Nullable<int> i = new Nullable<int>();
i.Equals(null);
Nullable i=new Nullable();
结果属性HasValue on i的值为false。它不是null,而是一个具有空值的值类型。或者只是一个空的null。对于任何给定的T,最好的方法是将null转换为空的
null

知道它使行i.Equals(null)更容易理解。这是一种合成糖,用于以下用途

Nullable<int> i = new Nullable<int>();
Nullable<int> i = new Nullable<int>();
i.Equals(null);
Nullable i=new Nullable();
i、 等于(空);

类型
Nullable
仅覆盖等于(对象)。但是,此方法的实现将空值视为等于空的可空值。所以它的行为是正确的。

为了回答您的附带问题,Nullable是一个带有T:struct约束的结构。那么,即使int?i=零;如果为null,则i是可空结构的实例。

但是,无论它在后台做什么,我们都将其称为i.Equals(null),当i为null时,它返回true。对于任何其他对象,它都应该返回false。@jcasso,可空的通常是。。。古怪的,经常以意想不到的方式表现。部分混淆是我不能为null,因为它实际上是一个值类型。最好将其视为一个空的可空值。至少你承认这很奇怪:)我认为我是唯一的一个。请注意,静态方法
Object.Equals(null,null)
将返回true,因此公认
null
等于
null
。调用
null.Equals(y)
时得到
NullReferenceException
的唯一原因是引用类型上的实例方法调用的语义要求;它与
等于
本身的语义无关。因为
Nullable
不是引用类型,所以这不适用。正如我在另一篇文章中指出的,I.Equals(null)没有调用Object.Equals。这是一个限制为可空类型的虚拟调用。结构可以接受空值吗?你能定义car4=null?就CLR而言,结构不能有
null
值。在C#中,当您编写
int时?x=null
,您实际上正在编写
int?x=新整数?()
。这里根本没有真正的
null
。但是当你做int的时候?i=,CLR将该合法值放入i的value属性中。另外,仅供参考,Nullable覆盖Equals方法,查看调用int下面的IL?i=零;CLR加载它分配给变量的地址,然后将一个空的可空对象(带有空字段)初始化到该地址。@pavel:用更简洁的方式来回答你的上一个问题,我在第二条注释中想说什么:)。如果
汽车?ncar1=
是一个
null的
,然后
ncar1==null
ncar1。Equals(null)
通常是相同的。两者都只需检查
ncar1.HasValue
是否为
false
。但是如果我们也有
车?ncar2=
,然后
ncar1==ncar2
ncar1.Equals(ncar2)
可能不同,这取决于
Car
struct type是否以与
.Equals
的适当重载等效的方式重载
运算符=
(可能是
.Equals(object))
汽车覆盖
或刚刚被
系统覆盖。ValueType
,或可能是
。等于(汽车)
(如果宣布超载)。