正确的覆盖Equals()和GetHashCode()的方法

126

我以前从未尝试过这个,所以希望有人能向我展示正确的实现方法来覆盖 Except() 和 GetHashCode() 方法。

我正在尝试修改类,以便可以使用 LINQ Except() 方法。

public class RecommendationDTO{public Guid RecommendationId { get; set; }
public Guid ProfileId { get; set; }
public Guid ReferenceId { get; set; }
public int TypeId { get; set; }
public IList<TagDTO> Tags { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime? ModifiedOn { get; set; }
public bool IsActive { get; set; }
public object ReferencedObject { get; set; }
public bool IsSystemRecommendation { get; set; }
public int VisibilityScore { get; set; }

public RecommendationDTO()
{
}

public RecommendationDTO(Guid recommendationid,
                            Guid profileid,
                            Guid referenceid,
                            int typeid,
                            IList<TagDTO> tags,
                            DateTime createdon,
                            DateTime modifiedon, 
                            bool isactive,
                            object referencedobject)
{
    RecommendationId = recommendationid;
    ProfileId = profileid;
    ReferenceId = referenceid;
    TypeId = typeid;
    Tags = tags;
    CreatedOn = createdon;
    ModifiedOn = modifiedon;
    ReferencedObject = referencedobject;
    IsActive = isactive;
}

public override bool Equals(System.Object obj)
{
    // If parameter is null return false.
    if (obj == null)
    {
        return false;
    }

    // If parameter cannot be cast to Point return false.
    RecommendationDTO p = obj as RecommendationDTO;
    if ((System.Object)p == null)
    {
        return false;
    }

    // Return true if the fields match:
    return (ReferenceId == p.ReferenceId);// && (y == p.y);
}

public bool Equals(RecommendationDTO p)
{
    // If parameter is null return false:
    if ((object)p == null)
    {
        return false;
    }

    // Return true if the fields match:
    return (ReferenceId == p.ReferenceId);// && (y == p.y);
}

//public override int GetHashCode()
//{
//    return ReferenceId;// ^ y;
//}}
我已经查看了 http://msdn.microsoft.com/en-us/library/ms173147.aspx,但我希望有人能够在我的示例中展示给我。任何帮助都将不胜感激。谢谢。

在你链接的页面上:“在非不可变类型中覆盖运算符==不是一个好主意。” 有其他更好的方法使Except()工作。 - H H
不建议重载等于运算符“==”,但重载Equals并不是不推荐的。 - Souhaieb Besbes
@SouhaiebBesbes - 强烈建议将 ==Equals() 保持同步。 - H H
3
Visual Studio 2017将生成这些方法:https://learn.microsoft.com/en-us/visualstudio/ide/reference/generate-equals-gethashcode-methods - Matt Morgan
3个回答

155

你可以像这样在你的类中重写Equals()和GetHashCode()方法:

public override bool Equals(object obj)
{
    var item = obj as RecommendationDTO;

    if (item == null)
    {
        return false;
    }

    return this.RecommendationId.Equals(item.RecommendationId);
}

public override int GetHashCode()
{
    return this.RecommendationId.GetHashCode();
}

我不需要实现IEquatable<>吗?:public class RecommendationDTO : IEquatable<RecommendationDTO>... 当我这么做时,我会得到一个错误:DataTransferObjects.RecommendationDTO没有实现接口成员System.IEquatable<DataTransferObjects.RecommendationDTO>.Equals(DataTransferObjects.RecommendationDTO)。 - Nugs
11
这是一个非常基础的解决方案,没有考虑最佳实践,特别是在哈希代码生成和重写相关的==和!=运算符方面。 - LostNomad311
2
在一般情况下,仅使用check是不够的,因为obj可能是从当前类派生的一个实例。 - ovolko
那么那些派生自System.ValueType的类型呢,比如从System.Object派生的class不同的struct呢? - code_dredd
@code_dredd 对于结构体请参考这个答案 - BornToCode
1
模式匹配也将考虑 null。if (!(obj is RecommendationDTOitem)) { return false } - TwoFingerRightClick

17
public override bool Equals(System.Object obj)
{
    // Check if the object is a RecommendationDTO.
    // The initial null check is unnecessary as the cast will result in null
    // if obj is null to start with.
    var recommendationDTO = obj as RecommendationDTO;

    if (recommendationDTO == null)
    {
        // If it is null then it is not equal to this instance.
        return false;
    }

    // Instances are considered equal if the ReferenceId matches.
    return this.ReferenceId == recommendationDTO.ReferenceId;
}

public override int GetHashCode()
{
    // Returning the hashcode of the Guid used for the reference id will be 
    // sufficient and would only cause a problem if RecommendationDTO objects
    // were stored in a non-generic hash set along side other guid instances
    // which is very unlikely!
    return this.ReferenceId.GetHashCode();
}

1
如果对象没有id属性怎么办? - Muflix

16

当使用主键作为重写Equals()方法中的相等性测试时,要小心,因为它仅在对象持久化后才起作用。在此之前,您的对象尚未有主键,而内存中的对象ID全部为零。

如果任一对象ID为零,我使用base.Equals()方法,但可能还有更可靠的方法。


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