.Equals返回意外结果

时间:2017-12-18 12:10:02

标签: c# domain-driven-design

请参阅以下代码:

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。我希望它能在无限循环中运行。

1 个答案:

答案 0 :(得分:1)

为什么你期望无限循环?返回true而不是false

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

不是因为母亲是平等的吗?它们具有相同的name,并且没有&#34; grandmom&#34;。他们的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,但如果母亲也是平等的,它将递归检查。

另一种方法是更改​​Equals中现有ValueType的签名:

public override bool Equals(Object other)