Search code examples
c#containsiequalitycomparer

Inline Comparer


I have a class Person with a Name property. I have a collection of persons. I have a method to add a new person but I need to check of the collection already contains the person.

I would like to use coll.Contains(newPerson,[here is the comparer]) where the comparer will make the comparison on the name property. Is it possible to make the comparison inline (anonymously) without creating a new class implementing IEqualityComparer?


Solution

  • In the case you don't want duplicate Person objects, and want to operate on that collection as a set, you can use a HashSet<Person> instead which when calling its Add method will do the check if such a person already exists. For that to work, you can implement IEquatable<Person> in your class. It would look roughly like this:

    public class Person : IEquatable<Person>
    {
        public Person(string name)
        {
            Name = name;
        }
    
        public string Name { get; private set; }
    
        public bool Equals(Person other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return string.Equals(Name, other.Name, StringComparison.OrdinalIgnoreCase);
        }
    
        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != this.GetType()) return false;
            return Equals((Person) obj);
        }
    
        public override int GetHashCode()
        {
            return (Name != null ? Name.GetHashCode() : 0);
        }
    
        public static bool operator ==(Person left, Person right)
        {
            return Equals(left, right);
        }
    
        public static bool operator !=(Person left, Person right)
        {
            return !Equals(left, right);
        }
    }
    

    And now you can use it in your HashSet<Person> like this:

    void Main()
    {
        var firstPerson = new Person { Name = "Yuval" };
        var secondPerson = new Person { Name = "yuval" };
        var personSet = new HashSet<Person> { firstPerson };
        Console.WriteLine(personSet.Add(secondPerson)); // Will print false.
    }
    

    Note this won't give you the flexibility of multiple comparers, but this way you won't have to create a new class implementing IEqualityComparer<T>.