Reputation: 22814
Could someone explain how does Union
in LINQ work?
It is told that it merges two sequences and removes duplicates.
But can I somehow customize the duplicate removal behavior - let's say if I wish to use the element from the second sequence
in case of duplicate or from the first sequence
.
Or even if I wish to somehow combine those values in the resulting sequence?
How should that be implemented?
I guess I described the problem incorrectly, let's say we have some value:
class Value {
String name
Int whatever;
}
and the comparer used performs a x.name == y.name
check.
And let's say that sometimes I know I should take the element from the second sequence, because it's whatever
field is newer / better than the whatever
field of the first sequence.
Anyway, I would use the sequence1.Union(sequence2)
or sequence2.Union(sequence1)
variation of the methods.
Thank you
Upvotes: 11
Views: 12657
Reputation: 292405
You can use second.Union(first)
instead of first.Union(second)
. That way, it will keep the items from second
rather than the items from first
.
Upvotes: 16
Reputation: 108790
When the object returned by this method is enumerated, Union enumerates first and second in that order and yields each element that has not already been yielded.
http://msdn.microsoft.com/en-us/library/bb341731.aspx
So the elements from whichever sequence you use as the left parameter take precedence over the elements from right parameter.
The important thing about this is that it's well defined and documented behavior and not just an implementation detail that might change in the next version of .net.
As a side-note when you implement an IEqualityComparer<T>
it's important to use consistent Equals
and GetHashCode
. And in this case I prefer to explicitly supply an equality comparer to the union method instead of having the Equals
of the object itself return true
for objects which are not identical for all purposes.
Upvotes: 9
Reputation: 137128
If the elements are duplicates then it doesn't matter which list they are taken from - unless your equality comparer doesn't take all properties of the element into account of course.
If they aren't really duplicates then they'll both appear in the resultant union.
UPDATE
From your new information at the minimum you should write a new equality operator that takes whatever
into account. You can't just use sequence1.Union(sequence2)
or sequence2.Union(sequence1)
unless all the elements want taking from one sequence or the other.
At the extreme you'll have to write your own Union
extension method which does this for you.
Upvotes: 5