Search code examples
c#linqiequalitycompareriequatable

Custom object using Except failing to use IEqualityComparer<T>


here is the object code:

public class DlpItem : IEqualityComparer<DlpItem>
{   
    public string Text { get; set; }
    public int Id { get; set; }

    public DlpItem(int pId)
    {
        Text = string.Empty;
        Id = pId;
    }

    public override bool Equals(object obj)
    {
        return Id == (obj as DlpItem).Id;
    }

    public bool Equals(DlpItem a, DlpItem b)
    {
        return a.Id == b.Id;
    }

    public int GetHashCode(DlpItem item)
    {
        return Id.GetHashCode();
    }
}

And I have two lists as follows:

var list1 = new List<DlpItem>();
list1.Add(new DlpItem(1));
list1.Add(new DlpItem(2));


var list2 = new List<DlpItem>();
list2.Add(new DlpItem(1));
list2.Add(new DlpItem(2));

var delItems = list1.Except(list2).ToList<DlpItem>();

delItems always has both items in it. What am I missing here?

EDIT: Code now implements IEquatable

public class DlpItem : IEqualityComparer<DlpItem>, IEquatable<DlpItem>
{   
    public string Text { get; set; }
    public int Id { get; set; }


    public override bool Equals(object obj)
    {
        return Id - (obj as DlpItem).Id == 0;
    }

    public bool Equals(DlpItem a, DlpItem b)
    {
        return a.Id == b.Id;
    }

    public bool Equals(DlpItem item)
    {
        return item != null && Id == item.Id;
    }

    public int GetHashCode(DlpItem item)
    {
        return Id.GetHashCode();
    }
}

Solution

  • In your example, you don't actually add anything to list2... a simple enough mistake, but there is a more significant issue:

    It needs to be IEquatable<T> not an IEqualityComparer<T>; also, you might want to ensure the hashcode can't change; most simply by making Id read-only:

    public class DlpItem : IEquatable<DlpItem>
    {
        public string Text { get; set; }
        private readonly int id;
        public int Id { get { return id; } }
    
        public DlpItem(int id)
        {
            Text = "";
            this.id = id;
        }
    
        public override bool Equals(object obj)
        {
            return Equals(obj as DlpItem);
        }
    
        public bool Equals(DlpItem other)
        {
            return other != null && this.Id == other.Id;
        }
        public override int GetHashCode()
        {
            return Id.GetHashCode();
        }
    }