Reputation: 23
I need to get to the bottom of this as I have researched the issue but I just do not get it.
Simple Object Here:
Dim Person As New Person
Dim myPeopleList as New List(Of Person)
Person.Name = "John"
Person.Age = 33
myPeopleList.Add(Person)
Works... BUT
MyPeopleList.Remove(Person)
Does not work.
What am I missing here? What can I do instead of looping through MyPeopleList comparing the name or the age
Upvotes: 0
Views: 74
Reputation: 74605
If you do this:
Dim myPeopleList As New List(Of Person)
Dim person As New Person
person.Name = "John"
person.Age = 33
myPeopleList.Add(person)
myPeopleList.Remove(person)
It works fine. This is because your Person inherits from Object, and in .NET by default two objects are equal if their memory address is equal. In this example above, the memory addresses are by definition equal because the same variable reference is used for the add (hence held in the list) as it then also passed in for remove.
It also means you could do this:
Dim person As New Person
person.Name = "John"
person.Age = 33
myPeopleList.Add(person)
Dim otherPerson = person '
myPeopleList.Remove(otherPerson)
The remove will still work because otherPerson
and person
are a reference to the same data at the same memory address
This, however, won't work:
Dim person As New Person
person.Name = "John"
person.Age = 33
myPeopleList.Add(person)
Dim otherPerson As New Person
otherPerson.Name = "John"
otherPerson.Age = 33
myPeopleList.Remove(otherPerson)
Because even though the data inside the person is the same, they aren't the same object at the same memory location. If you were to take a dump of your memory, you'd find it like ...John..33..........John..33......
- literally there are two different objects that happen to have the same data
Remember, by default (unless we decide otherwise) objects are compared based on where they are in memory (it's a pretty good default really; two objects can't occupy the same space)
So let's decide otherwise. Let's make a rule that a Person equals another Person if their Name and Age are the same value:
Class Person
Public Age As Int32
Public Name As String
Public Overrides Function Equals(obj As Object) As Boolean
Dim p = DirectCast(obj, Person)
Return p.Name = Me.Name AndAlso p.Age = Me.Age
End Function
End Class
If we override the default Equals (which compares memory addresses) with our own version that compares a passed-in object (which is expected to be a person in this case) values for Name and Age with the current values, then all of a sudden we can do this:
Dim person As New Person
person.Name = "John"
person.Age = 33
myPeopleList.Add(person)
Dim otherPerson As New Person
otherPerson.Name = "John"
otherPerson.Age = 33
myPeopleList.Remove(otherPerson)
When it's doing the remove, List will visit every item in its internal array, asking "this passed in otherPerson .Equals the one in my list?" and when our version of Equals, which has replaced the default version, returns True, the list can say "ah, this person in my array is the person being sought for removal - remove it"
A couple of things worth pointing out: First that:
GetHashCode
so it can be quickly used to assess whether two objects are different, than you can end up with a situation where a Dictionary considers two objects not equal but a List considers them equal. For example with our Person above, where we override Equals but not GetHashCode, and made two new Person objects with the same name/age then list.Add(person) list.Contains(otherPerson)
would return true, but dictionary.Add(person, ...) dictionary.ContainsKey(otherPerson, ...)
would return FalseSecond:
Upvotes: 3
Reputation: 6111
My guess is that when you are trying to remove an item, you aren't passing the same reference as the one that was added.
If you want to remove the item where the person's name is John and who is 33 years old, then you should query the collection for the item first, then remove the returned result:
Dim john = myPeopleList.Single(Function(person) person.Name = "John" AndAlso person.Age = 33)
myPeopleList.Remove(john)
The issue that you can run into this is what would happen if there is more than one John who is 33 years old or there is none at all? The example I just gave would fail because Single expects there to be exactly one instance.
If this can occur, then an alternative would be to modify the underlying list to only include people who do not meet your conditions:
myPeopleList = myPeopleList.Where(Function(person) person.Name <> "John" AndAlso person.Age <> 33).ToList()
Upvotes: 0