Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/259.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# 两个相等的.NET对象don';我不说是_C#_Equals_Equality - Fatal编程技术网

C# 两个相等的.NET对象don';我不说是

C# 两个相等的.NET对象don';我不说是,c#,equals,equality,C#,Equals,Equality,我有以下代码: object val1 = 1; object val2 = 1; bool result1 = (val1 == val2);//Equals false bool result2 = val1.Equals(val2); //Equals true 怎么回事?使用.Equals()方法是否是解决此问题的唯一方法?是=检查引用是否相等。在要比较内容的位置使用Equals 您可能想知道,为什么对象如此。将整型(值类型)设置为对象变量时,会发生称为装箱的操作。此操作将值类型包装

我有以下代码:

object val1 = 1;
object val2 = 1;

bool result1 = (val1 == val2);//Equals false
bool result2 = val1.Equals(val2); //Equals true

怎么回事?使用.Equals()方法是否是解决此问题的唯一方法?

是<代码>=检查引用是否相等。在要比较内容的位置使用
Equals


您可能想知道,为什么对象如此。将整型(值类型)设置为对象变量时,会发生称为装箱的操作。此操作将值类型包装到对象中,并将其放入堆中并返回引用。这种情况会发生两次,引用会变得不同(尽管值相同)。

这是因为当您将它们强制转换为对象时,它们会“转换”为对int值的引用。这两个参考值并不相等。
但是equals比较引用的值而不是引用。

运算符
==
是静态的,而不是虚拟的,因此行为由静态类型而不是运行时类型决定。引用类型的对象上的
==
的默认实现是比较引用(尽管类型可以实现不同的行为,例如
string
)。您有两个不同的对象,它们没有相同的引用,因此
=
返回false

正如你所指出的,解决办法是使用Equals。Equals是一种虚拟方法。由于
value1
具有运行时类型
Int32
,因此您最终会调用它。从.NET Reflector中,您可以看到此功能的实现如下所示:

public override bool Equals(object obj)
{
    return ((obj is int) && (this == ((int) obj)));
}
换句话说,它检查参数的类型是否为
int
,如果是,则将其强制转换并使用为
int
定义的
=
。这将比较整数的值

使用.Equals()方法是否是解决此问题的唯一方法


另一种方法是将对象强制转换为
int
,然后使用
=
,就像
Int32.Equals的实现一样

如果两个对象指向内存中的相同空间,则它们是相等的

val1 == val1; //Equals true
正如tc所指出的,您可以使操作员过载

public static bool operator ==(Object a, Object b)
这样,运算符
==
的行为将是此方法定义的行为


您还应该重载运算符
=当您重载时,检查两个对象是否相同。事实并非如此。它们表示相同的数字,但存储在内存中的不同位置

val1 == val1; //Equals true

这就像比较两个苹果。两者都是苹果,外观相同,但它们是不同的对象。

如果使用的不是
对象,而是自定义类,则可以重写==和!=操作员,并且可能应该实现
IEqualityComparer
接口

public static bool operator ==(MyType left, MyType right)
{
    //code here, don't forget about NULLS when writing comparison code!!!
}

public static bool operator !=(MyType left, MyType right)
{
    return !(left == right);
}

public bool Equals(MyType x, MyType y)
{
    return (x == y);
}

public int GetHashCode(MyType obj)
{
    return base.GetHashCode();
}
代码对应的框中包含两个整数,并比较装箱(=)生成的两个对象。此比较仅供参考

  .locals init ([0] object val1,
           [1] object val2,
           [2] bool result1,
           [3] bool result2)
  IL_0000:  nop
  IL_0001:  ldc.i4.1
  IL_0002:  box        [mscorlib]System.Int32
  IL_0007:  stloc.0
  IL_0008:  ldc.i4.1
  IL_0009:  box        [mscorlib]System.Int32
  IL_000e:  stloc.1
  IL_000f:  ldloc.0
  IL_0010:  ldloc.1
  IL_0011:  ceq
  IL_0013:  stloc.2
  IL_0014:  ldloc.0
  IL_0015:  ldloc.1
  IL_0016:  callvirt   instance bool [mscorlib]System.Object::Equals(object)
  IL_001b:  stloc.3
对于.Equals,它调用Object.Equals,后者调用Int32.Equals(对对象的虚拟方法调用):


这将强制转换为int并将值作为整数进行比较,这是一种值类型比较。

除非存在运算符重载。这似乎是唯一正确的答案(或者,至少,我非常确定您可以在字符串上使用==并使其按预期工作)。好的,我不明白为什么在这里使用Equals。根据文档,“Equals的默认实现支持引用类型的引用相等,值类型的位相等。引用相等意味着比较的对象引用引用同一个对象。”@John C:问得好。我的最新答案是否更清楚?是的,谢谢,现在有道理了。我假设对于您自己的用户定义类,您需要提供您自己的相等定义。假设它们相等,但两个不同的实例dude,==和.Equals做两件不同的事情操作员检查val1和val2是否占用相同的内存空间(参考)。Equals检查内容是否相等。您也可以使用
对象。Equals(对象,对象)
静态方法,该方法首先尝试使用
=
运算符比较对象,然后在两个参数均不为空时尝试
对象。Equals(对象)
方法。我建议这样做的原因是,在调用
object.Equals(object,object)
之前,您不必检查null,而在调用
object.Equals(object)
时则需要检查null。