在基类中实现IEquatable接口

4

我正在使用ASP.NET MVC和EntityFramework的代码优先。

我试图为将保存到我的数据库中的所有对象创建一个基类(这里称为实体类)。

在基类中实现IEquatable有好的方法吗?在我的实现中,我检查类型和ID - 这是一个好的做法吗?这将始终返回最终派生类型吗?那么中间的父类呢?

对象

public abstract class Entity : IEquatable<Entity>
{
    public int ID { get; set; }
    public string Name { get; set; }

    public Entity(string Name)
    {
        this.Name = Name;
    }

    public override string ToString() { return Name; }
    public override int GetHashCode() { return ID.GetHashCode(); }
    public override bool Equals(object obj) { return this == (Entity)obj; }
    public bool Equals(Entity other) { return this == other; }
    public static bool operator ==(Entity x, Entity y) { return Object.ReferenceEquals(x, y) ? true : ((object)x == null || (object)y == null) ? false : (x.GetType() == y.GetType() && x.ID.Equals(y.ID)); }
    public static bool operator !=(Entity x, Entity y) { return !(x == y); }
}

public abstract class Content : Entity
{
    public Content(string Name) : base(Name)
    {

    }
}

public class Page : Content
{
            public string Body { get; set; }
    public Page(string Name) : base(Name)
    {

    }
}

public class User : Entity
{
    public User(string Name) : base(Name)
    {

    }
}

数据库

每个衍生的对象类型通常存在于单独的数据库中。然而,有些继承父对象之间存在中间对象,它们共享主键。

假设有以下三个表格,分别包含以下列: 实体

  • 内容
    • ID
    • 名称
  • 页面
    • ID
    • 正文
  • 用户
    • ID
    • 名称

因此,页面和内容表格共享一个主键。


只有在ID是只读的情况下才应该这样做。 - paparazzo
2个回答

1
  1. 没有必要实现IEquitable接口,它不会提供任何价值(既不是性能价值,也不是可读性价值)。
  2. 在比较中,你仅依赖于引用相等性检查。你应该同时检查ID相等性。
  3. 你的GetHashCode()实现不够优化,你应该包括实体类型。
  4. 你确定所有实体都有Name属性吗?在基类中,你应该包括在有界上下文中的每个实体都有的属性。

这里我详细描述了这个主题: 域对象基类


2
“没有必要实现IEquitable” - 你为什么这么说?有几个原因 - user585968
@MickyD 只有在类型为结构体时才有意义。否则,没有显著的性能提升。除非您正在开发具有高性能要求并需要所有微观优化的软件,否则您不会注意到差异。 - Vladimir
1
它并非出于性能原因而完成,而是为了帮助您编写更好的代码。如果您有一个名为Entity的类,并且它具有一个Id属性,该属性在程序中标识该实体,并且您想让具有相同Id的Entity类的多个实例也被视为相等(例如在检查集合是否包含该对象时),最好的方法是使类实现IEquatable接口。 - Sasino

0

你的实现是正确的。

但要小心操作。如果你有部分加载的对象,它们可能被认为是相等的,但可能并不具有完全相同的值。

如果你想有时使用默认的相等比较,有时使用基于ID的相等比较,请创建一个单独的帮助类来实现IEqualityComparer<Entity>接口。


部分加载是什么意思? - William
@William,使用EF时,这通常只涉及到关系。如果一个“页面”有“内容”,那么您可以从数据库中加载一个“页面”实例,而不加载引用的“内容”。然后,在某个地方单独加载相同的“页面”实例,但是要加载引用的“内容”。现在,您有两个不同的“页面”实例,一个具有“内容”,另一个没有。它们相等吗?答案取决于特定情况的需求,可能是肯定的,也可能是否定的。我曾经遇到过这个问题。 - Samuel Neff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接