簡體   English   中英

聯盟與Linq的Concat

[英]Union Vs Concat in Linq

我對UnionConcat有疑問。 我想在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 ,不會更改引用。

如果您將覆蓋EqualsGetHashCode (用於選擇不同的項目),則不會通過引用比較項目:

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多個項目,那么您將看到UnionConcat之間的區別:

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項序列,因為兩個輸入序列中的所有四個項都是不同的

UnionConcat行為相同,因為如果沒有自定義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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM