Correct way to override Equals() and GetHashCode() [duplicate]
Asked Answered
P

3

128

I have never really done this before so i was hoping that someone could show me the correct what of implementing a override of Except() and GetHashCode() for my class.

I'm trying to modify the class so that i can use the LINQ Except() method.

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;
//}}

I have taken a look at http://msdn.microsoft.com/en-us/library/ms173147.aspx but i was hoping someone could show me within my own example.

Any help would be appreciated.

Thank you

Poker answered 16/2, 2012 at 19:15 Comment(4)
On the page you linked to: "It is not a good idea to override operator == in non-immutable types." There are other and better ways to make Except() work.Inglebert
@Henk Holterman overriding equality operator == is not recommended; overriding Equals isn't not recommended.Funiculate
@SouhaiebBesbes - it is (very strongly) recommended to keep == and Equals() in sync.Inglebert
VS 2017 will generate these learn.microsoft.com/en-us/visualstudio/ide/reference/…Snodgrass
G
159

You can override Equals() and GetHashCode() on your class like this:

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();
}
Goggleeyed answered 16/2, 2012 at 19:24 Comment(6)
Do i not have to implement IEquatable<>?: public class RecommendationDTO : IEquatable<RecommendationDTO>... When i do i get a error: DataTransferObjects.RecommendationDTO does not implement interface member System.IEquatable<DataTransferObjects.RecommendationDTO>.Equals(DataTransferObjects.RecommendationDTO)Poker
This is a very basic solution that doesn't address best practices , especially with the hash code generation and overriding the related == and != operators.Gorrono
as check is not enough in the general case because obj could be an instance of a class derived from the current oneIndiscretion
What about those that derive from System.ValueType, such as structs instead of classes which derive from System.Object?Provencal
@Provencal For structs see this answer.Scherzo
pattern matching also will account for null if (!(obj is RecommendationDTOitem)) { return false }Kevakevan
I
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();
}
Ise answered 16/2, 2012 at 19:28 Comment(1)
what if object does not have an id property ?Photodrama
B
16

Be careful when using a primary key as your test for equality in overriding Equals() because it only works AFTER the object has been persisted. Prior to that your objects don't have primary keys yet and the IDs of the ones in memory are all zero.

I use base.Equals() if either of the object IDs is zero but there probably is a more robust way.

Bucky answered 24/9, 2012 at 20:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.