1

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?

M.kazem Akhgary
  • 18,645
  • 8
  • 57
  • 118
ehh
  • 3,412
  • 7
  • 43
  • 91

2 Answers2

1

You can use linq instead.

bool contains = coll.Any(p => p.Name == newPerson.Name);

You can add any condition here as you want. for example as WaiHaLee noted you can make compare ignore case.

bool contains = coll.Any(p => p.Name.Equals(newPerson.Name, StringComparison.OrdinalIgnoreCase));
M.kazem Akhgary
  • 18,645
  • 8
  • 57
  • 118
  • I'd suggest you make the name comparison using the invariant culture and ignoring case so that "john smith" will compare to "JOHN SMITH" and handles the [Turkish I](https://msdn.microsoft.com/en-us/library/ms994325.aspx#cltsafcode_topic4). – Wai Ha Lee Oct 18 '15 at 08:14
1

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>.

Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321