96 votes

Union Vs Concat dans Linq

J'ai une question sur Union y Concat .

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"

Les résultats ci-dessus sont attendus, mais dans le cas de List<T> J'obtiens le même résultat avec les deux Union y Concat .

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

Mais les deux se comportent de la même manière en cas de List<T> .

Des suggestions, s'il vous plaît ?

123voto

Sergey Berezovskiy Points 102044

Le retour de l'Union Distinct valeurs. Par défaut, il compare les références des éléments. Vos éléments ont des références différentes, ils sont donc tous considérés comme différents. Lorsque vous effectuez un cast vers le type de base X La référence n'est pas modifiée.

Si vous voulez passer outre Equals y GetHashCode (utilisé pour sélectionner des éléments distincts), alors les éléments ne seront pas comparés par référence :

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();
    }
}

Mais tous vos articles ont une valeur différente de ID . Tous les articles sont donc considérés comme différents. Si vous fournissez plusieurs articles avec le même ID alors vous verrez la différence entre Union y 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

Votre exemple initial fonctionne, car les entiers sont des types de valeurs et ils sont comparés par valeur.

55voto

Rawling Points 21932

Concat retourne littéralement les éléments de la première séquence, suivis des éléments de la deuxième séquence. Si vous utilisez Concat sur deux séquences de 2 éléments, vous obtiendrez toujours une séquence de 4 éléments.

Union est essentiellement Concat suivi par Distinct .

Dans vos deux premiers cas, vous vous retrouvez avec des séquences à deux éléments car, entre eux, chaque paire de carrés d'entrée a exactement deux éléments distincts.

Dans votre troisième cas, vous vous retrouvez avec une séquence de 4 éléments car les quatre éléments de vos deux séquences d'entrée sont distincts .

18voto

Tim Schmelter Points 163781

Union y Concat se comportent de la même manière puisque Union ne peut pas détecter les doublons sans un IEqualityComparer<X> . C'est juste pour voir si les deux sont la même référence.

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();
    }
}

Maintenant vous pouvez l'utiliser dans la surcharge de Union :

var comparer = new XComparer();
a5 = lstX1.Cast<X>().Union(lstX2.Cast<X>(), new XComparer());

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X