I have two collections of type ICollection<MyType>
called c1
and c2
. I'd like to find the set of items that are in c2
that are not in c1
, where the heuristic for equality is the Id
property on MyType
.
What is the quickest way to perform this in C# (3.0)?
Use Enumerable.Except
and specifically the overload that accepts an IEqualityComparer<MyType>
:
var complement = c2.Except(c1, new MyTypeEqualityComparer());
Note that this produces the set difference and thus duplicates in c2
will only appear in the resulting IEnumerable<MyType>
once. Here you need to implement IEqualityComparer<MyType>
as something like
class MyTypeEqualityComparer : IEqualityComparer<MyType> {
public bool Equals(MyType x, MyType y) {
return x.Id.Equals(y.Id);
}
public int GetHashCode(MyType obj) {
return obj.Id.GetHashCode();
}
}
If using C# 3.0 + Linq:
var complement = from i2 in c2
where c1.FirstOrDefault(i1 => i2.Id == i1.Id) == null
select i2;
Loop through complement to get the items.
public class MyTypeComparer : IEqualityComparer<MyType>
{
public MyTypeComparer()
{
}
#region IComparer<MyType> Members
public bool Equals(MyType x, MyType y)
{
return string.Equals(x.Id, y.Id);
}
public int GetHashCode(MyType obj)
{
return base.GetHashCode();
}
#endregion
}
Then, using Linq:
c3 collection = new collection().add(c1);
c3.add(c2);
var items = c3.Distinct(new MyTypeComparer());
You could also do it using generics and predicates. If you need a sample, let me know.