0

I have a list of Persons inside a Company Class.

public class Company{
    IList<Person> persons;
}

Then I have a List of companies,

IList<Company> companies;

Now I have a name (say "Lasantha"). If this name is a part of the name of any person in a company, I want to find that company. I tried using companies.Contains() method. I overrided the object.Equals method, inside the Person class as this,

public override bool Equals(object o)
        {
            var other = o as Person;
            return this.Name.ToLower().Contains(other.Name.ToLower());
        }

But this is not working. It's not calling this Equal method as well. Can someone help me please.

Thank you.

Lasantha Bandara
  • 809
  • 3
  • 10
  • 22

5 Answers5

5

Overriding the equality comparison in this manner is wrong.

Equality should be transitive: if

"FooBar".Equals("Foo") == true

then it must also hold that

"Foo".Equals("FooBar") == true

However, in this case you are using Contains which will break the transitivity because "FooBar" contains "Foo", but "Foo" does not contain "FooBar". Apart from that, you should not override the Equals method on a class unless each and every last comparison between objects of that class will have the same semantics (which in this case seems highly dubious).

So, given that overriding Equals is not the solution, what should you do?

One convenient way is to use LINQ:

var companiesWithPeopleWithLasanthaInTheirName = 
    companies.Where(c => c.persons.Any(p => p.Name.Contains("Lasantha")));

However the above comparison is case-sensitive, so if you need it to not be you have to tweak it; there is an answer in this question: Case insensitive 'Contains(string)'

Community
  • 1
  • 1
Jon
  • 428,835
  • 81
  • 738
  • 806
2

You can use Linq, something like

var temp = companies.Where(p => p.People.Any(q => q.Name.Contains("Lasantha")));

Here is the full example;

public class Example
{
    private IList<Company> companies;
    public Example()
    {
        Person p1 = new Person(){Name = "Lasantha"};
        Person p2 = new Person(){Name = "Red Kid"};
        Company comp = new Company();
        comp.People = new List<Person>();

        comp.People.Add(p1);
        comp.People.Add(p2);

        companies = new List<Company>();
        companies.Add(comp);

        var temp = companies.Where(p => p.People.Any(q => q.Name.Contains("Lasantha")));
    }
}

public class Company
{
    public IList<Person> People
    {
        get;
        set;
    }
}

public class Person
{
    public string Name { get; set; }
}
daryal
  • 14,643
  • 4
  • 38
  • 54
1

You need to overload Equals so that it takes a Person as parameter. Otherwise it will default to reference comparison.

public override bool Equals(Person p)
{
   //...
}

Then as msdn states, you may need to provide CompareTo (IComparable) as well.

Louis Kottmann
  • 16,268
  • 4
  • 64
  • 88
1

I don't think you need to override Equals when you can get this as

you should be using where to filter the companies and then use Any on the Person list to get the ones matching your name criteria

companies.Where(c => c.persons.Any(p => p.Name.Contains("Value here"));
V4Vendetta
  • 37,194
  • 9
  • 78
  • 82
0

You're searching for

  1. a list of characters ("Lasantha")
  2. inside a list of Persons
  3. inside a list of Companies

Well, other contributors already described how to do it correctly

Kelon
  • 821
  • 10
  • 10