none
How to use IEqualityComparer in LINQ RRS feed

  • Question

  • Hello:

    I have some code, trying to use IEqualityComparer in LINQ:

    public class Obj4Equal
    {  
        public int ID { get; set; }
        public string Name { get; set; }
        public decimal Value { get; set; }
        public DateTime TimeStamp { get; set; }
    }
    
    
    public class ObjComparer : IEqualityComparer<Obj4Equal>
    {
        public bool Equals(Obj4Equal x, Obj4Equal y)
        {
        if (x.Name.Equals(y.Name) && (x.Value.Equals(y.Value)))
        {
        return true;
        }
    else
        {
        return false;
        }
    }
    
    public int GetHashCode(Obj4Equal obj)
    {
    unchecked
        {
        int hash = 100;
        hash = hash * 10 + obj.ID.GetHashCode();
        hash = hash * 10 + obj.Value.GetHashCode();
        return hash;
        }
        }
    }
    
    static void Main(string[] args)
    {
    Obj4Equal obj1 = new Obj4Equal
    { ID = 1, Name = "A", Value = 1, TimeStamp = DateTime.Now };
    Obj4Equal obj2 = new Obj4Equal
    { ID = 2, Name = "B", Value = 2, TimeStamp = DateTime.Now };
    List<Obj4Equal> total_objs = new List<Obj4Equal>();
    total_objs.Add(obj1);
    total_objs.Add(obj2);
    var search_obj1 = total_objs.Where(x == obj1).FirstOrDefault();
    }
    
    

    I want to find the element from a list of object, but I don't know how to use IEqualityComparer in LINQ expression.

    Please advice


    • Edited by zydjohn Monday, October 22, 2018 12:02 PM
    Monday, October 22, 2018 12:01 PM

Answers

  • If there is only expected to be one item then use FirstOrDefault. If there can be multiple then use Where.

    var comparer = new ObjComparer();
    
    var item = total_objs.FirstOrDefault(f => comparer.Equals(f, obj1));

    Note that you don't really need IEqualityComparer for finding items. You can use a simple lambda.

    Also, generally you don't implement IEqualityComparer on a standalone type. It is generally implemented by the type that needs it. The exception would be when comparison could be different things (e.g. strings). If you're going to implement IEqualityComparer then note that you should be very careful about how you implement it because it can produce inconsistent results which will cause havoc. In your specific case it works only if you explicitly use ObjComparer. However that isn't easily discoverable so the comparison should be on the type. When implementing this interface on a ref type there are a lot more cases to handle. Refer to MSDN on how to do this properly. Ideally you should be using a struct instead.


    Michael Taylor http://www.michaeltaylorp3.net

    • Marked as answer by zydjohn Monday, October 22, 2018 2:30 PM
    Monday, October 22, 2018 2:06 PM
    Moderator

All replies

  • https://www.codeproject.com/Articles/94272/A-Generic-IEqualityComparer-for-Linq-Distinct
    Monday, October 22, 2018 12:25 PM
  • If there is only expected to be one item then use FirstOrDefault. If there can be multiple then use Where.

    var comparer = new ObjComparer();
    
    var item = total_objs.FirstOrDefault(f => comparer.Equals(f, obj1));

    Note that you don't really need IEqualityComparer for finding items. You can use a simple lambda.

    Also, generally you don't implement IEqualityComparer on a standalone type. It is generally implemented by the type that needs it. The exception would be when comparison could be different things (e.g. strings). If you're going to implement IEqualityComparer then note that you should be very careful about how you implement it because it can produce inconsistent results which will cause havoc. In your specific case it works only if you explicitly use ObjComparer. However that isn't easily discoverable so the comparison should be on the type. When implementing this interface on a ref type there are a lot more cases to handle. Refer to MSDN on how to do this properly. Ideally you should be using a struct instead.


    Michael Taylor http://www.michaeltaylorp3.net

    • Marked as answer by zydjohn Monday, October 22, 2018 2:30 PM
    Monday, October 22, 2018 2:06 PM
    Moderator