Reputation: 48
Ok, so I have a List of type my own class, which in turn has parameters such as strings and integers, and I want to check inside my list with Contains() if I have a match with something a user would input.
As for the example you can assume there are already members in the list.
class Person
{
public string Name {get; set;}
public int Age {get; set;}
public int Id {get; set;}
public Person()
{
}
}
class PersonList : Person
{
List<Person> personList = new List<Person>();
public bool Exist(int inputParameter)
{
if (personList.Contains(new Person { Id = inputParameter }))
{
return true;
}
else
{
return false;
}
}
}
Now even when I'm sure the input belongs to an already existing member of the list, my Exist method always returns false. Has anybody have any clue as to what I might not be doing right?
Upvotes: 0
Views: 2723
Reputation: 416059
The .Contains()
method uses the default equality comparer, which means it calls the .Equals()
method for the type to find a match.
For reference types like your Person
class, the default method inherited from Object
uses reference equality, meaning it will only return true
if they are the exact same object instance. If you want a different type of comparison, you should overload the Equals()
method in the type (and implement IEquatable<T>
and override GetHashCode()
while you're at it).
public class Person : IEquatable<Person>
{
public string Name {get; set;}
public int Age {get; set;}
public int Id {get; set;}
public bool Equals(Person other)
{
return other is Object && this.Id == other.Id;
}
public override bool Equals(Object other)
{
if (other is Person) return Equals((Person)other);
return false;
}
public override int GetHashCode()
{ //naive implementation. This is adequate as long as you're **SURE** all instances will have a unique/correct `Id` value.
return this.Id.GetHashCode();
}
}
Going beyond this, I would not build a separate PersonList
type. The List<Person>
generic collection almost certainly already does the things you need.
That out of the way, it's still worthwhile to address how you might implement the Exist()
method from the original PersonList
class. One thing I would do here is avoid trying to allocate new objects to complete the search. With that in mind:
public bool Exist(int inputParameter)
{
return personList.Any(p => p.Id == inputParameter);
}
Note, this will still currently allocate a new iterator object in most cases, but work is being done to make these linq operations more memory-friendly over time. It's also a whole lot less code. If you have a function that gives you a boolean
result, there's no good reason to put it in an if()
block just to return that same result.
And if we want to get really aggressive on the allocations, we can do it like this:
public bool Exist(int inputParameter)
{
foreach(var p in personList)
{
if (p.Id == inputParameter) return true;
}
return false;
}
Upvotes: 3
Reputation: 4913
You can also use Any
instead Contains
, try to change the code of Exist
method to:
public bool Exist(int inputParameter)
{
return personList.Any(person => person.Id == inputParameter);
}
Upvotes: 3
Reputation: 62522
You can use Any
public bool Exist(inputParameter)
{
if (personList.Any(person => person.Id == inputParameter))
{
return true;
}
else
{
return false;
}
}
Which you can collapse to just:
public bool Exist(inputParameter)
{
return personList.Any(person => person.Id == inputParameter);
}
Upvotes: 1