You can find the implementation of Enumerable.Union in the reference source .
Here's how it works:
public static IEnumerable<TSource> Union<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second) { if (first == null) throw Error.ArgumentNull("first"); if (second == null) throw Error.ArgumentNull("second"); return UnionIterator<TSource>(first, second, null); } static IEnumerable<TSource> UnionIterator<TSource>(IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer) { Set<TSource> set = new Set<TSource>(comparer); foreach (TSource element in first) if (set.Add(element)) yield return element; foreach (TSource element in second) if (set.Add(element)) yield return element; }
As you can see, Union will iterate over both enumerations and derive objects from these sources. Like all Linq methods, it will not create a list, but work as a generator function. The list will only be created when .ToList() called.
To avoid duplication, he will use Set and try to add an element before yielding it. If the addition to the set was successful, then the element was not there yet, so it can be obtained.
Note that sets are very effective at finding if an item exists in it. They provide the search for elements in amortized constant time mode. Thus, it is definitely more efficient than your objList2.Contains , which will need to be objList2.Contains through the list again and again to determine if every item exists in it.
Also note that Union built to maintain the order of input enums. If you donβt need it, you can skip this completely and just use Set first. This is especially good if you plan to add new items to the same target set all the time, since it reuses the structure:
HashSet<object> set = new HashSet<object>(); foreach (β¦) { List<object> objList1 = β¦
It would be even better if you avoided creating objList1 in the first place and simply added your elements to the set directly - if this is possible for your use case.
source share