2017-12-18 188 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