1. ホーム
  2. c#

[解決済み] LinqにおけるUnionとConcatの比較

2023-02-14 22:48:54

質問

私は、以下の点について質問します。 UnionConcat .

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"

上記の結果は予想されるものですが、もし List<T> の両方から同じ結果を得ています。 UnionConcat .

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> .

何かご提案があればお願いします。

どのように解決するのですか?

ユニオンの戻り値 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

整数は値型であり、値で比較されるため、最初のサンプルは動作します。