views:

65

answers:

3

If have a class of Widgets like this:

public class Widget
{
   public double Price { get; set; }
   public string Type { get; set; }
   public int ID { get; set; }
   public string Name { get; set; }
}

And create a list of them:

List<Widget> Widgets = new List<Widget>
   {
       new Widget {ID = 1, Name = "One", Price = 3.00, Type = "Gooy"},
       new Widget {ID = 2, Name = "Two", Price = 5.00, Type = "Crispy"},
       new Widget {ID = 2, Name = "Three", Price = 3.00, Type = "Hard"},
       new Widget {ID = 2, Name = "Four", Price = 3.00, Type = "Chewy"},
       new Widget {ID = 2, Name = "Five", Price = 2.50, Type = "Gooy"}
   };

And then I call IEnumerable.Distinct with a custom comparer like so:

IEqualityComparer<Widget> widgetComparer = 
   new LambdaComparer<Widget>((item1, item2) => item1.Price == item2.Price);

Widgets.Distinct(widgetComparer);

Then (as I see it) there should be 3 objects returned (one for each price category).

What is the Type of the 3.00 one (Gooy, Hard or Chewy)?

Does it pick one? (I am trying to understand distinct better because my real distinct is not giving me distinct results.)

+2  A: 

Hey,

Distinct takes whatever the comparer determines; so if there are 3 different objects with the same price, and your custom comparer only looks at the price, then it should consider them one and the same, depending on how the comparison takes place.

HTH.

Brian
But what if they are not the same? What if each one is different? Which item do I get back? Or does it null out non-common values (doubtful).
Vaccano
It would find the first non-distinct one in order, then compare the other two and ignore them. So I believe it would be the first in the list, as it iterates through. Order would be important.
Brian
@brian you are not garantied that the first or any other specific is returned. You are not even garantied that the same one will be returned on two subsequent runs (see my answer for an explanation) relying on any specific being return would also violate the contract of Distinct. They are by definition equal (or there's a bug in the comparer :))
Rune FS
+2  A: 

Well the answer has to be 'it depends' the distinct should consider the three the same and only keep one, which is usually the first but since Distinct is an extension method it Will aldo depend on the implementation of the extension and on method resulution "finding" the method. Which again depends on "nearness" so calling Distinct on the same IEnumerable object with the same Comparer might yield two different results. E.g. If the "nearest" implementation of Distinct differs on the two call sites

Rune FS
+2  A: 

This is really a philosophy question. You are defining equality to mean that the price is equal. Therefore, based on your definition, they are equal regardless of what the Type value is.

So, the answer is: It doesn't matter which one gets returned. They are all the same. You shouldn't care or predict which one gets returned, and the implementation of Distinct reserves the right to change it on you... because they are all the same from an a == b == c perspective.

If it turns out that you do care which one gets returned, than you have defined your equality comparison incorrectly and you need to re-think your equality function.

Brian Genisio
I really don't care which one gets returned as long as it really is one of them.
Vaccano