Reputation: 633
Can someone please explain why these two methods are returning different values?
List<CustomerSummary> summaries = new List<CustomerSummary>();
for (var i = 0; i < 10; i++)
{
var summary = new CustomerSummary() { ID = 1, Name = "foo", balance = 50.00 };
if (!summaries.Contains(summary))
summaries.Add(summary);
}
-
List<CustomerSummary> summaries = new List<CustomerSummary>();
for (var i = 0; i < 10; i++)
{
var summary = new CustomerSummary() { ID = 1, Name = "foo", balance = 50.00 };
if (!summaries.Any(s=> s.ID == summary.ID))
summaries.Add(summary);
}
The first method has 10 items in the list while the second has 1. Why does the first ( Contains() ) method never evaluate as true?
What I'm trying to ask is why are 2 objects of the same type with the same values for each property not evaluating as equivalent (in the first method)?
Upvotes: 6
Views: 240
Reputation: 24302
List<T>.Contains
method determines equality by using the default equality comparer. And here you are trying to compare two different objects. Both may have all the properties filled with matching values, but those are two different objects. If you want to really use the Contains method here, you have to implement the IEquatable<T>.Equals
method in your CustomerSummary
object.
Upvotes: 2
Reputation: 66479
Your first block of code is creating a new instance inside the loop, and then immediately checking to see if that exact instance is already in the collection. It can't be - you just created it.
You might as well write it like this:
List<CustomerSummary> summaries = new List<CustomerSummary>();
for (var i = 0; i < 10; i++)
{
var summary = new CustomerSummary { ID = 1, Name = "foo", balance = 50.00 };
summaries.Add(summary);
}
Your second block of code is checking for the existence of any item in the collection with a matching ID. Since you've hard-coded the ID to be 1, you're only going to add an item the first time around. Every instance created after that will return false in the if
statement, and will not be added.
You could change that behavior by changing the ID:
for (var i = 0; i < 10; i++)
{
var summary = new CustomerSummary { ID = i, Name = "foo", balance = 50.00 };
if (!summaries.Any(s=> s.ID == summary.ID))
summaries.Add(summary);
}
Again, the if
statement is no longer even necessary, since you know the ID can't possibly already exist in the collection, so you could just remove the check.
Upvotes: 3
Reputation: 4487
That's because Contains()
matches the reference of the Summary
.. and not the ID
.
Every time you do a
var summary = new CustomerSummary() { ID = 1, Name = "foo", balance = 50.00 };
in your loop, you create a new instance of CustomerSummary
and hence a new reference is stored in summary
, thought the values of every property within the CustomerSummary
asre exactly same..
Upvotes: 2
Reputation: 156
hi in the first function you trying to use contains on the entire object and not on property like you do in the second function try change first like this
List<CustomerSummary> summaries = new List<CustomerSummary>();
for (var i = 0; i < 10; i++)
{
var summary = new CustomerSummary() { ID = 1, Name = "foo", balance = 50.00 };
if (!summaries.Select(s=>s.ID).Contains(summary.ID))
summaries.Add(summary);
}
Upvotes: 1
Reputation: 8322
if (!summaries.Contains(summary))
This will check whole touple(row)
{ ID = 1, Name = "foo", balance = 50.00 }
And
This will check single element Id=1.
Upvotes: 0