Union Vs Concat in Link

I have a question about Union and Concat . I think both behave the same in the case of List<T> .

 var a1 = (new[] { 1, 2 }).Union(new[] { 1, 2 }); // O/P : 1 2 var a2 = (new[] { 1, 2 }).Concat(new[] { 1, 2 }); // O/P : 1 2 1 2 var a3 = (new[] { "1", "2" }).Union(new[] { "1", "2" }); // O/P : "1" "2" var a4 = (new[] { "1", "2" }).Concat(new[] { "1", "2" }); // O/P : "1" "2" "1" "2" 

Expected Result,

But incase List<T> I get the same result.

 class X { public int ID { get; set; } } class X1 : X { public int ID1 { get; set; } } class X2 : X { public int ID2 { get; set; } } var lstX1 = new List<X1> { new X1 { ID = 10, ID1 = 10 }, new X1 { ID = 10, ID1 = 10 } }; var lstX2 = new List<X2> { new X2 { ID = 10, ID2 = 10 }, new X2 { ID = 10, ID2 = 10 } }; var a5 = lstX1.Cast<X>().Union(lstX2.Cast<X>()); // O/P : a5.Count() = 4 var a6 = lstX1.Cast<X>().Concat(lstX2.Cast<X>()); // O/P : a6.Count() = 4 

But both behave the same as List<T> .

Any suggestions please?

+50
c # linq
Nov 16 '12 at 13:26
source share
3 answers

Union returns Distinct values. By default, it will compare item references. Your items have different links, so they are all considered different. When you click on the base type X link does not change.

If you override Equals and GetHashCode (used to select individual elements), then the elements will not be compared by reference:

 class X { public int ID { get; set; } public override bool Equals(object obj) { X x = obj as X; if (x == null) return false; return x.ID == ID; } public override int GetHashCode() { return ID.GetHashCode(); } } 

But all your items have different ID values. Thus, all items are still considered different. If you provide multiple elements with the same ID , then you will see the difference between Union and Concat :

 var lstX1 = new List<X1> { new X1 { ID = 1, ID1 = 10 }, new X1 { ID = 10, ID1 = 100 } }; var lstX2 = new List<X2> { new X2 { ID = 1, ID2 = 20 }, // ID changed here new X2 { ID = 20, ID2 = 200 } }; var a5 = lstX1.Cast<X>().Union(lstX2.Cast<X>()); // 3 distinct items var a6 = lstX1.Cast<X>().Concat(lstX2.Cast<X>()); // 4 

Your original pattern works because integers are value types and they are compared by value.

+63
Nov 16 '12 at 13:29
source share
— -

Concat literally returns elements from the first sequence, followed by elements from the second sequence. If you use Concat for two sequences of 2 elements, you will always get a sequence of 4 elements.

Union is essentially Concat , followed by Distinct .

In the first two cases, you get 2-position sequences, because between them each pair of input fillets has exactly two different elements.

In your third case, you get a sequence of 4 elements, because all four elements in your two input sequences are different.

+27
Nov 16 '12 at 13:29
source share

Union and Concat behave the same, since Union cannot detect duplicates without a custom IEqualityComparer<X> . It just looks if both are the same links.

 public class XComparer: IEqualityComparer<X> { public bool Equals(X x1, X x2) { if (object.ReferenceEquals(x1, x2)) return true; if (x1 == null || x2 == null) return false; return x1.ID.Equals(x2.ID); } public int GetHashCode(X x) { return x.ID.GetHashCode(); } } 

Now you can use it when overloading Union :

 var comparer = new XComparer(); a5 = lstX1.Cast<X>().Union(lstX2.Cast<X>(), new XComparer()); 
+12
Nov 16 '12 at 13:32
source share



All Articles