2017-12-18 184 views
0

請參閱下面的代碼:.Equals返回意外的結果

public class ValueType<T> where T : class,new() 
    { 
     public virtual bool Equals(T other) 
     { 
      if (other == null) 
       return false; 
      Type t = GetType(); 
      Type otherType = other.GetType(); 
      if (t != otherType) 
       return false; 
      FieldInfo[] fields = t.GetFields(System.Reflection.BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); 
      foreach (FieldInfo field in fields) 
      { 
       object value1 = field.GetValue(other); 
       object value2 = field.GetValue(this); 
       if (value1 == null) 
       { 
        if (value2 != null) 
         return false; 
       } 
       else if (!value1.Equals(value2)) 
        return false; 
      } 
      return true; 
     } 
    } 

    class Tiger : ValueType<Tiger> { public string name; public Tiger mother; } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      Tiger t1 = new Tiger() { name = "Teri" }; 
      Tiger t2 = new Tiger() { name = "Teri" }; 
      Tiger t3 = new Tiger() { name = "Toni", mother=t1 }; 
      Tiger t4 = new Tiger() { name = "Toni", mother = t2 }; 
      bool Test1 = t4.mother.Equals(t3.mother); //Highlighed line 
      bool Test2 = t4.Equals(t3); 
     } 
    } 

我不明白爲什麼突出顯示的行返回false。我希望它運行在一個無限循環中。

+3

爲什麼你希望一個無限循環?它返回'true'順便說一句。這是不是預料到的,因爲兩個母親是平等的,他們有同樣的名字,沒有母親。他們的'mother'字段返回'null',因爲'Tiger'是一個引用類型(class): –

+1

我認爲他期待的!value1.Equals(value2)調用相同的等號函數 – chrispepper1989

+0

@ chrispepper1989,是的。 +1。 – w0051977

回答

1

爲什麼你期待一個無限循環?繼回報truefalse

bool Test1 = t4.mother.Equals(t3.mother); . 

那不是預期的,因爲這兩個母親都是平等的嗎?他們有相同的name,沒有「祖母」。他們的mother字段返回null,因爲Tiger是引用類型(類)。

爲什麼t4.Equals(t3)返回false

因爲您已聲明它爲Object,所以使用Object.Equals只是比較引用。如果你嘗試將它投射到Tiger這個Equals將被調用。

這就是爲什麼這不會導致一個無限循環,但只是返回false(不一樣的參考):

...else if (!value1.Equals(value2)) 

注意,你沒有覆蓋Equals。如果你願意,你會得到預期的行爲:

class Tiger : ValueType<Tiger> { 
    public string name; public Tiger mother; 
    public override bool Equals(object obj) 
    { 
     return ((ValueType<Tiger>) obj).Equals(this); 
    } 
} 

現在,按預期工作。它不會導致無限遞歸,因爲在某些時候,父母mother將是null,但它會遞歸檢查母親是否相等。

另一種方式是改變的簽名已經存在於ValueTypeEquals

public override bool Equals(Object other) 
+0

由t4.Equals(t3)返回false? – w0051977

+0

@ w0051977:因爲這些字段被聲明爲Object,因此將使用Object.ReferenceEquals。你沒有重寫'Equals'。我編輯了我的答案 –

+1

對不起。我期待第二次調用.Equals調用通用方法。這就是我期待無限循環的原因。我看到現在發生了什麼。 – w0051977