为什么此对象相等测试失败?

时间:2009-05-27 16:07:11

标签: c#

进行以下课程和单元测试。

public class Entity
    {
        public object Id { get; set; }

        public override bool Equals(object obj)
        {
            return this == (Entity)obj;
        }

        public static bool operator == (Entity base1, Entity base2)
        {
            if (base1.Id != base2.Id)
            {
                return false;
            }

            return true;
        }

        public static bool operator != (Entity base1, Entity base2)
        {
            return (!(base1.Id == base2.Id));
        }
    }

        [TestMethod]
        public void Test()
        {
            Entity e1 = new Entity { Id = 1 };
            Entity e2 = new Entity { Id = 1 };
            Assert.IsTrue(e1 == e2); //Always fails
        }

有人可以解释为什么会失败吗?

8 个答案:

答案 0 :(得分:8)

您的Id媒体资源属于object。当您使用1作为每个实例的Id构造两个实例时,您将最终得到两个不同的盒装对象。然后,您将使用 reference 相等来比较这些对象。

建议更改以解决此问题:

  • 如果合适,请将Id的类型更改为int类型。
  • 使用静态object.Equals方法比较Ids而不是==

其中任何一个都可行,但第一个是优选的IMO。

如果您感兴趣,还有其他各种方法可以使实施更清洁,但我知道这可能只是一个虚拟的例子。快速列表一目了然:

  • 您应该覆盖GetHashCode以及Equals
  • 您的Equals覆盖不应无条件地执行转换,因为如果对象的类型错误,则会抛出异常。如果类型错误,则返回false。
  • 您当前的==实现可以简化为

    return base1.Id == base2.Id;
    
  • 您的==实施应执行无效检查
  • 通常最好通过返回!(base1 == base2)来实施!=,除非您需要专家行为。
  • 在非密封课程中覆盖Equals可能会有问题。除非你计划继承,否则值得密封课程(国际海事组织 - 这可能会引起争议)。

答案 1 :(得分:3)

因为您依赖比较器的对象引用:

public object Id { get; set; }

替换

    public static bool operator == (Entity base1, Entity base2)
    {
        if (base1.Id != base2.Id)
        {
            return false;
        }

        return true;
    }

使用

    public static bool operator == (Entity base1, Entity base2)
    {
        return object.Equals(base1.Id, base2.Id);
    }

答案 2 :(得分:2)

因为e1.Id和e2.Id是不同的对象。即使它们具有相同的值,它们也不是同一个对象,因此base1.Id == base2.Id失败。

答案 3 :(得分:2)

你的equals实现只是比较引用,而不是对象的内容。你实际上是在比较两个指针,因为你已经创建了两个独立的对象,你的相等就会失败。

有几篇关于如何正确实现Equals的文章,这是一个开始:

http://weblogs.asp.net/tgraham/archive/2004/03/23/94870.aspx

对于数据库实体,您可以通过比较数据库ID来执行快捷方式Equals实现,假设系统中两个具有相同ID的对象被视为“相等”。

答案 4 :(得分:2)

您的Id是一个对象,而不是一个int。对于对象,==运算符不会检查值是否相等。

答案 5 :(得分:1)

因为你的Id属性是一个对象。

1(作为int)被装入堆对象,但每个1被装入一个单独的实例。由于Id是一个对象,base1.Id!= base2.Id条件检查引用相等而不是 value 相等,这就是你想要的。将Id更改为int,或使用Equals()而不是!=应该修复它。

答案 6 :(得分:0)

如果您将Id成员设为int,则会有效。但正如CookieOfFortune所说,当你比较两个对象时,它会查看它们是否是完全相同的对象,而不是它们是否具有相同的值。

答案 7 :(得分:0)

将Id的类型更改为int或其他值类型。问题是你正在比较2个对象,我认为这是你重载==运算符来解决的问题