[英]Union Vs Concat in Linq
我對Union
和Concat
有疑問。 我想在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"
上述結果是預期的,
但是Incase of List<T>
我得到了相同的結果。
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
但兩者的行為與List<T>
。
有什么建議嗎?
Union返回Distinct
值。 默認情況下,它將比較項目的引用。 您的商品有不同的參考,因此它們都被認為是不同的。 當您轉換為基本類型X
,不會更改引用。
如果您將覆蓋Equals
和GetHashCode
(用於選擇不同的項目),則不會通過引用比較項目:
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();
}
}
但是您的所有商品都有不同的ID
值。 所以所有項目仍然被認為是不同 如果您將提供具有相同ID
多個項目,那么您將看到Union
和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
您的初始樣本有效,因為整數是值類型,它們按值進行比較。
Concat
逐字地返回第一個序列中的項目,然后是第二個序列中的項目。 如果您在兩個2項目序列上使用Concat
,您將始終獲得4項序列。
Union
實際上是Concat
其次是Distinct
。
在前兩種情況下,您最終會得到兩項序列,因為在它們之間,每對輸入序列都有兩個不同的項目。
在第三種情況下,最終得到一個4項序列,因為兩個輸入序列中的所有四個項都是不同的 。
Union
和Concat
行為相同,因為如果沒有自定義IEqualityComparer<X>
Union
無法檢測到重復項。 它只是看兩者是否是相同的參考。
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();
}
}
現在你可以在Union
的重載中使用它:
var comparer = new XComparer();
a5 = lstX1.Cast<X>().Union(lstX2.Cast<X>(), new XComparer());
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.