为什么比较同一个类的两个实例返回false?

时间:2017-05-17 13:03:08

标签: c#

  Consider the below code  -  

 // given class abc
     class abc
        {
          public string firstName {get;set;}
          public string lastName {get;set;}
        }

class program
{
  static void Main()
  {
   var a1 = new abc();   
   var a2 = new abc();  // object of same class


   if (a1==a2)    //always return false
     {
       // some code here
      }
  }
}

9 个答案:

答案 0 :(得分:2)

当您使用==时,您正在比较引用而不是对象内容

因为当你这样做时,引用不一样

   var a1 = new abc();   
   var a2 = new abc(); 

a1在内存中分配(称为实例),a2在内存中有另一个分配(它将是另一个实例) 请看看如何切换GetHashcode

答案 1 :(得分:1)

它是同一个类但不是同一个类的实例。假设您要比较每个由班级代表的2名学生

  

学生

该类的两个实例很可能带有不同的值,例如姓名,年龄等。这些应该(出于显而易见的原因)不相等。

答案 2 :(得分:1)

必须描述哪些类实例是相同的,例如当且仅当两个abc个实例具有相等的firstNamelastName属性值时,才允许它们相等:

class abc {
  public string firstName { get; set; }
  public string lastName { get; set; }

  public override bool Equals(object obj) {
    abc other = obj as abc;

    if (object.ReferenceEquals(null, other))
      return false;
    else
      return string.Equals(firstName, other.firstName) &&
             string.Equals(lastName, other.lastName);
  }

  public override int GetHashCode() {
    return (lastName == null ? 0 : lastName.GetHashCode()) ^ 
           (firstName == null ? 0 : firstName.GetHashCode());
  }
}

....

var a1 = new abc();   
var a2 = new abc();  // object of same class

if (a1 == a2) // now it'll return true
{
   // some code here
}

// it'll be still false: a1 and a2 are different references
if (object.ReferenceEquals(a1, a2)) { 
  // some other code here
}

如果您不提供EqualsGetHashCode方法,。Net将使用参照等式(如果它们具有相同的引用,则实例相等):在您的情况下a1a2是不同的引用,默认情况下为a1 != a2

有关详细信息,请参阅https://msdn.microsoft.com/en-us/library/bsc2ak47(v=vs.110).aspx

答案 3 :(得分:1)

默认情况下,operator ==通过确定两个引用是否指示同一对象来测试引用相等性。如果要更改此行为,则应覆盖operator ==。

答案 4 :(得分:1)

这样想:

var alicesBall = new GreenBall();
var bobsBall = new GreenBall();

你现在有两个球:爱丽丝的球和鲍勃的球。如果有人会问你们两个球是否是同一个球 - 不一样善良 - 你可能会说“不”。

但如果有人要问两个球是否都有相同类型的球 - 在这种情况下是一个绿球 - 你可能会回答“当然”。

您要比较的是a1和a2是否具有相同的类型。

答案 5 :(得分:0)

比较对象的属性更好。 这是我的建议:

if (a1.firstName==a2.firstName && a1.lastName == a2.lastName){
   //some code here
}

答案 6 :(得分:0)

使用==运算符比较两个对象会比较内存中的地址,而不是对象本身。在为它们提供相同的值后尝试使用Object.Equals()方法或定义自己的.Equals()方法。

来自MSDN:

  

Equals的默认实现支持引用相等   引用类型和值类型的按位相等。参考   等于意味着被比较的对象引用引用   同一个对象。按位相等意味着被比较的对象具有   相同的二进制表示。

     

请注意,派生类型可能会覆盖要实现的Equals方法   价值平等。值相等意味着比较对象具有   相同的值,即使它们具有不同的二进制表示。对于   例如,考虑两个表示数字1.10的Decimal对象   和1.1000。 Decimal对象没有按位相等,因为   他们有不同的二元表示来解释   不同数量的尾随零。但是,对象具有价值   平等,因为数字1.10和1.1000被认为是相等的   比较目的,因为尾随零是无关紧要的。

这引自以下内容:link

“现在,在幕后,CLR实际上实现了托管对象引用作为垃圾收集器拥有的对象的地址,但这是一个实现细节。没有理由除了效率和灵活性之外还必须这样做。 C#引用可以通过仅对垃圾收集器有意义的opaque句柄来实现,坦率地说,这是我更喜欢它们的方式。“句柄”恰好是运行时的地址实际上是一个实现细节,我应该既不知道也不依赖。(这是封装的全部要点;客户不必知道。)“

就程序员而言,它只是一个指针/地址。但对于编译器来说,这只是简单的地址。因此,虽然它们的使用方式不同(一种类型是安全的,另一种类型不是),但就编译器而言,它们都是指针,直到Microsoft决定以不同方式实现CLR。

答案 7 :(得分:0)

首先要知道的是,对象(类)是通过引用而非值创建的,当您使用==比较器时,它将在处理"时检查引用相等性。 REF"数据类型,因为它是该数据类型的默认Equals行为。 (希望有意义,如果不是我可以更具体)。

要解决您的问题,您应该覆盖Equals方法来比较存储在对象内部的值,而不是检查引用相等性。

示例:

class abc
{
    public string firstName {get;set;}
    public string lastName {get;set;}

    // custom equality comparer
    public override bool Equals(object other) 
    {
        if ( other is abc )
        {
           abc comparer = other as abc;
           if ( comparer != null )
           {
               return string.Equals(comparer.firstName, this.firstName)
                      &&
                      string.Equals(comparer.lastName, this.lastName);
           }
        }
        return base.Equals(other);
    }
}

答案 8 :(得分:-1)

因为在两个不同的内存位置有两个不同的对象。

您可以使用GetType()和typeof()来比较类。