Comparaisons et tris dans les collectionsComparisons and Sorts Within Collections

Les classes System.Collections effectuent des comparaisons dans quasiment tous les processus impliqués dans la gestion des collections, que ce soit pendant la recherche d'un élément à supprimer ou le renvoi d'une valeur d'une paire clé-valeur.The System.Collections classes perform comparisons in almost all the processes involved in managing collections, whether searching for the element to remove or returning the value of a key-and-value pair.

Les collections utilisent généralement un comparateur d'égalité et/ou un comparateur de classement.Collections typically utilize an equality comparer and/or an ordering comparer. Deux constructions sont utilisées pour les comparaisons.Two constructs are used for comparisons.

Vérification de l'égalitéChecking for equality

Les méthodes telles que Contains, IndexOf, LastIndexOfet Remove utilisent un comparateur d'égalité pour les éléments de collection.Methods such as Contains, IndexOf, LastIndexOf, and Remove use an equality comparer for the collection elements. Si la collection est générique, les éléments font l'objet d'une comparaison d'égalité, selon les consignes suivantes :If the collection is generic, than items are compared for equality according to the following guidelines:

De plus, certaines surcharges de constructeur pour les collections de dictionnaires acceptent une implémentation IEqualityComparer<T>, qui est utilisée pour comparer l'égalité de clés.In addition, some constructor overloads for dictionary collections accept an IEqualityComparer<T> implementation, which is used to compare keys for equality. Pour obtenir un exemple, consultez le constructeur Dictionary<TKey,TValue>.Dictionary<TKey,TValue> .For an example, see the Dictionary<TKey,TValue>.Dictionary<TKey,TValue> constructor.

Détermination de l'ordre de triDetermining sort order

Les méthodes telles que BinarySearch et Sort utilisent un comparateur de classement pour les éléments de collection.Methods such as BinarySearch and Sort use an ordering comparer for the collection elements. Les comparaisons peuvent être effectuées entre les éléments d'une collection, ou entre un élément et une valeur spécifiée.The comparisons can be between elements of the collection, or between an element and a specified value. Pour comparer des objets, il existe le default comparer et le explicit comparer.For comparing objects, there is the concept of a default comparer and an explicit comparer.

Le comparateur par défaut repose sur au moins l'un des objets comparés pour implémenter l'interface IComparable .The default comparer relies on at least one of the objects being compared to implement the IComparable interface. Il est recommandé d'implémenter IComparable sur toutes les classes utilisées en tant que valeurs dans une collection de listes ou en tant que clés dans une collection de dictionnaires.It is a good practice to implement IComparable on all classes are used as values in a list collection or as keys in a dictionary collection. Pour une collection générique, la comparaison d’égalité est déterminée selon ce qui suit :For a generic collection, equality comparison is determined according to the following:

  • Si le type T implémente l'interface générique System.IComparable<T> , le comparateur par défaut est la méthode IComparable<T>.CompareTo(T) de cette interface.If type T implements the System.IComparable<T> generic interface, then the default comparer is the IComparable<T>.CompareTo(T) method of that interface

  • Si le type T implémente l'interface non générique System.IComparable , le comparateur par défaut est la méthode IComparable.CompareTo(Object) de cette interface.If type T implements the non-generic System.IComparable interface, then the default comparer is the IComparable.CompareTo(Object) method of that interface.

  • Si le type T n'implémente aucune interface, il n'existe aucun comparateur par défaut. Un comparateur ou un délégué de comparaison doit donc être fourni explicitement.If type T doesn’t implement either interface, then there is no default comparer, and a comparer or comparison delegate must be provided explicitly.

Pour fournir des comparaisons explicites, certaines méthodes acceptent une implémentation IComparer en tant que paramètre.To provide explicit comparisons, some methods accept an IComparer implementation as a parameter. Par exemple, la méthode List<T>.Sort accepte une implémentation System.Collections.Generic.IComparer<T> .For example, the List<T>.Sort method accepts an System.Collections.Generic.IComparer<T> implementation.

Le paramètre de culture actuel du système peut affecter les comparaisons et les tris d’une collection.The current culture setting of the system can affect the comparisons and sorts within a collection. Par défaut, les comparaisons et les tris des classes Collections sont dépendants de la culture.By default, the comparisons and sorts in the Collections classes are culture-sensitive. Pour ignorer le paramètre de culture et donc obtenir des résultats cohérents de comparaison et de tri, utilisez InvariantCulture avec des surcharges de membre qui acceptent CultureInfo.To ignore the culture setting and therefore obtain consistent comparison and sorting results, use the InvariantCulture with member overloads that accept a CultureInfo. Pour plus d’informations, consultez Performing Culture-Insensitive String Operations in Collections et Performing Culture-Insensitive String Operations in Arrays.For more information, see Performing Culture-Insensitive String Operations in Collections and Performing Culture-Insensitive String Operations in Arrays.

Exemple d'égalité et de triEquality and sort example

Le code suivant illustre une implémentation de IEquatable<T> et de IComparable<T> dans un objet métier simple.The following code demonstrates an implementation of IEquatable<T> and IComparable<T> on a simple business object. De plus, quand l'objet est stocké dans une liste, puis trié, vous verrez que l'appel de la méthode Sort() se traduit par l'utilisation du comparateur par défaut pour le type Part , et par l'implémentation de la méthode Sort(Comparison<T>) à l'aide d'une méthode anonyme.In addition, when the object is stored in a list and sorted, you will see that calling the Sort() method results in the use of the default comparer for the Part type, and the Sort(Comparison<T>) method implemented by using an anonymous method.

using System;
using System.Collections.Generic;
// Simple business object. A PartId is used to identify the type of part 
// but the part name can change. 
public class Part : IEquatable<Part> , IComparable<Part>
{
    public string PartName { get; set; }

    public int PartId { get; set; }

    public override string ToString()
    {
        return "ID: " + PartId + "   Name: " + PartName;
    }
    public override bool Equals(object obj)
    {
        if (obj == null) return false;
        Part objAsPart = obj as Part;
        if (objAsPart == null) return false;
        else return Equals(objAsPart);
    }
    public int SortByNameAscending(string name1, string name2)
    {
        
        return name1.CompareTo(name2);
    }

    // Default comparer for Part type.
    public int CompareTo(Part comparePart)
    {
          // A null value means that this object is greater.
        if (comparePart == null)
            return 1;
            
        else
            return this.PartId.CompareTo(comparePart.PartId);
    }
    public override int GetHashCode()
    {
        return PartId;
    }
    public bool Equals(Part other)
    {
        if (other == null) return false;
        return (this.PartId.Equals(other.PartId));
    }
    // Should also override == and != operators.

}
public class Example
{
    public static void Main()
    {
        // Create a list of parts.
        List<Part> parts = new List<Part>();

        // Add parts to the list.
        parts.Add(new Part() { PartName = "regular seat", PartId = 1434 });
        parts.Add(new Part() { PartName= "crank arm", PartId = 1234 });
        parts.Add(new Part() { PartName = "shift lever", PartId = 1634 }); ;
        // Name intentionally left null.
        parts.Add(new Part() {  PartId = 1334 });
        parts.Add(new Part() { PartName = "banana seat", PartId = 1444 });
        parts.Add(new Part() { PartName = "cassette", PartId = 1534 });
       

        // Write out the parts in the list. This will call the overridden 
        // ToString method in the Part class.
        Console.WriteLine("\nBefore sort:");
        foreach (Part aPart in parts)
        {
            Console.WriteLine(aPart);
        }


        // Call Sort on the list. This will use the 
        // default comparer, which is the Compare method 
        // implemented on Part.
        parts.Sort();


        Console.WriteLine("\nAfter sort by part number:");
        foreach (Part aPart in parts)
        {
            Console.WriteLine(aPart);
        }
       
        // This shows calling the Sort(Comparison(T) overload using 
        // an anonymous method for the Comparison delegate. 
        // This method treats null as the lesser of two values.
        parts.Sort(delegate(Part x, Part y)
        {
            if (x.PartName == null && y.PartName == null) return 0;
            else if (x.PartName == null) return -1;
            else if (y.PartName == null) return 1;
            else return x.PartName.CompareTo(y.PartName);
        });

        Console.WriteLine("\nAfter sort by name:");
        foreach (Part aPart in parts)
        {
            Console.WriteLine(aPart);
        }
       
        /*
       
            Before sort:
        ID: 1434   Name: regular seat
        ID: 1234   Name: crank arm
        ID: 1634   Name: shift lever
        ID: 1334   Name:
        ID: 1444   Name: banana seat
        ID: 1534   Name: cassette

        After sort by part number:
        ID: 1234   Name: crank arm
        ID: 1334   Name:
        ID: 1434   Name: regular seat
        ID: 1444   Name: banana seat
        ID: 1534   Name: cassette
        ID: 1634   Name: shift lever

        After sort by name:
        ID: 1334   Name:
        ID: 1444   Name: banana seat
        ID: 1534   Name: cassette
        ID: 1234   Name: crank arm
        ID: 1434   Name: regular seat
        ID: 1634   Name: shift lever

         */

    }
}
Imports System.Collections.Generic
' Simple business object. A PartId is used to identify the type of part 
' but the part name can change. 
Public Class Part
    Implements IEquatable(Of Part)
    Implements IComparable(Of Part)
    Public Property PartName() As String
        Get
            Return m_PartName
        End Get
        Set(value As String)
            m_PartName = Value
        End Set
    End Property
    Private m_PartName As String

    Public Property PartId() As Integer
        Get
            Return m_PartId
        End Get
        Set(value As Integer)
            m_PartId = Value
        End Set
    End Property
    Private m_PartId As Integer

    Public Overrides Function ToString() As String
        Return "ID: " & PartId & "   Name: " & PartName
    End Function

    Public Overrides Function Equals(obj As Object) As Boolean
        If obj Is Nothing Then
            Return False
        End If
        Dim objAsPart As Part = TryCast(obj, Part)
        If objAsPart Is Nothing Then
            Return False
        Else
            Return Equals(objAsPart)
        End If
    End Function

    Public Function SortByNameAscending(name1 As String, name2 As String) As Integer

        Return name1.CompareTo(name2)
    End Function

    ' Default comparer for Part.
    Public Function CompareTo(comparePart As Part) As Integer _
            Implements IComparable(Of ListSortVB.Part).CompareTo
        ' A null value means that this object is greater.
        If comparePart Is Nothing Then
            Return 1
        Else

            Return Me.PartId.CompareTo(comparePart.PartId)
        End If
    End Function
    Public Overrides Function GetHashCode() As Integer
        Return PartId
    End Function
    Public Overloads Function Equals(other As Part) As Boolean Implements IEquatable(Of ListSortVB.Part).Equals
        If other Is Nothing Then
            Return False
        End If
        Return (Me.PartId.Equals(other.PartId))
    End Function
    ' Should also override == and != operators.

End Class
Public Class Example
    Public Shared Sub Main()
        ' Create a list of parts.
        Dim parts As New List(Of Part)()

        ' Add parts to the list.
        parts.Add(New Part() With { _
             .PartName = "regular seat", _
             .PartId = 1434 _
        })
        parts.Add(New Part() With { _
             .PartName = "crank arm", _
             .PartId = 1234 _
        })
        parts.Add(New Part() With { _
             .PartName = "shift lever", _
             .PartId = 1634 _
        })


        ' Name intentionally left null.
        parts.Add(New Part() With { _
             .PartId = 1334 _
        })
        parts.Add(New Part() With { _
             .PartName = "banana seat", _
             .PartId = 1444 _
        })
        parts.Add(New Part() With { _
             .PartName = "cassette", _
             .PartId = 1534 _
        })


        ' Write out the parts in the list. This will call the overridden 
        ' ToString method in the Part class.
        Console.WriteLine(vbLf & "Before sort:")
        For Each aPart As Part In parts
            Console.WriteLine(aPart)
        Next


        ' Call Sort on the list. This will use the 
        ' default comparer, which is the Compare method 
        ' implemented on Part.
        parts.Sort()


        Console.WriteLine(vbLf & "After sort by part number:")
        For Each aPart As Part In parts
            Console.WriteLine(aPart)
        Next

        ' This shows calling the Sort(Comparison(T) overload using 
        ' an anonymous delegate method. 
        ' This method treats null as the lesser of two values.
        parts.Sort(Function(x As Part, y As Part)
                             If x.PartName Is Nothing AndAlso y.PartName Is Nothing Then
                                 Return 0
                             ElseIf x.PartName Is Nothing Then
                                 Return -1
                             ElseIf y.PartName Is Nothing Then
                                 Return 1
                             Else
                                 Return x.PartName.CompareTo(y.PartName)
                             End If
                         End Function)
        

        Console.WriteLine(vbLf & "After sort by name:")
        For Each aPart As Part In parts
            Console.WriteLine(aPart)
        Next

        '
        '        
        '            Before sort:
        '            ID: 1434   Name: regular seat
        '            ID: 1234   Name: crank arm
        '            ID: 1634   Name: shift lever
        '            ID: 1334   Name:
        '            ID: 1444   Name: banana seat
        '            ID: 1534   Name: cassette
        '
        '            After sort by part number:
        '            ID: 1234   Name: crank arm
        '            ID: 1334   Name:
        '            ID: 1434   Name: regular seat
        '            ID: 1444   Name: banana seat
        '            ID: 1534   Name: cassette
        '            ID: 1634   Name: shift lever
        '
        '            After sort by name:
        '            ID: 1334   Name:
        '            ID: 1444   Name: banana seat
        '            ID: 1534   Name: cassette
        '            ID: 1234   Name: crank arm
        '            ID: 1434   Name: regular seat
        '            ID: 1634   Name: shift lever

    End Sub
End Class

Voir aussiSee also