Use IEnumerable<Foo>.Distinct and implement your equality operator with the operator where the Baz property is checked, and the HasBar property HasBar ignored if Baz not equal. You can do this with && because if the left expression is false, the right expression is not evaluated.
Then a HasBar based HasBar with IEnumerable<Foo>.Where .
If you do not want to clutter your Foo object with the Equals operator, or you need different Equals implementations for different cases, then run a separate IEqualityComparer<Foo> .
This also has the advantage that you can completely not check the HasBar property when getting different values. If you miss a check in the class itself, it can cause subtle mistakes, because people can expect them to be equal. But with a well-known user mapping, it is unlikely that people will believe that it will ensure absolute equality.
Here is a sample code:
IEnumerable<Foo> selectedFoos = sampleDataSet .Distinct(new PerformantFooComparer()) .Where(f => f.HasBar); // ... private class PerformantFooComparer : IEqualityComparer<Foo> { public bool Equals(Foo x, Foo y) { bool isXNull = x == null; bool isYNull = y == null; return isXNull == isYNull && isXNull || ( x.Baz == y.Baz // && x.HasBar == y.HasBar // HasBar commented out to avoid performance overhead. // It is handled by a Where(foo => foo.HasBar) filter ); } public int GetHashCode(Foo obj) { if (obj == null) return 0; // See: http://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode int hash = 17; hash = hash * 23 + obj.Baz.GetHashCode(); // HasBar intentionally not hashed return hash; } }
source share