Vergleiche und Sortierungen innerhalb von Sammlungen

Die <xref:System.Collections>-Klassen führen bei nahezu allen Vorgängen zur Verwaltung von Auflistungen Vergleiche durch, sei es bei der Suche nach zu entfernenden Elementen oder bei der Rückgabe eines Schlüssel-Wert-Paars.

Auflistungen verwenden in der Regel einen Gleichheitsvergleich und/oder einen Reihenfolgenvergleich. Für Vergleiche werden zwei Konstrukte verwendet.

Durchführen von Gleichheitsüberprüfungen

Methoden wie Contains, <xref:System.Collections.IList.IndexOf%2A>, <xref:System.Collections.Generic.List%601.LastIndexOf%2A>und Remove verwenden einen Gleichheitsvergleich für die Elemente der Auflistung. Wenn die Auflistung generisch ist, werden die Elemente anhand der folgenden Richtlinien auf Gleichheit hin verglichen:

  • Wenn Typ T die generische Schnittstelle <xref:System.IEquatable%601> implementiert, dann ist der Gleichheitsvergleich die <xref:System.IEquatable%601.Equals%2A> -Methode dieser Schnittstelle.

  • Wenn der Typ T <xref:System.IEquatable%601>nicht implementiert, wird <xref:System.Object.Equals%2A?displayProperty=fullName> verwendet.

Darüber hinaus akzeptieren einige Konstruktorüberladungen für Wörterbuchauflistungen eine <xref:System.Collections.Generic.IEqualityComparer%601> -Implementierung, die zum Vergleichen von Schlüsseln auf Gleichheit hin verwendet wird. Ein Beispiel dafür finden Sie unter <xref:System.Collections.Generic.Dictionary%602.%23ctor%2A?displayProperty=fullName> -Konstruktor.

Festlegen der Sortierreihenfolge

Methoden, wie BinarySearch und Sort , verwenden einen Reihenfolgenvergleich für Elemente der Auflistung. Die Vergleiche können zwischen Elementen in der Auflistung oder zwischen einem Element und einem angegebenen Wert durchgeführt werden. Für den Vergleich von Objekten gibt es die Konzepte default comparer und explicit comparer.

Der Standardvergleich beruht auf dem Vergleich von mindestens einem Objekt, um die IComparable -Schnittstelle zu implementieren. Es ist empfehlenswert, IComparable in allen Klassen zu implementieren, die als Werte in einer Listenauflistung oder als Schlüssel in einer Wörterbuchauflistung verwendet werden. Bei einer generischen Auflistung wird der Gleichheitsvergleich gemäß dem Folgenden bestimmt:

  • Wenn Typ T die generische Schnittstelle <xref:System.IComparable%601?displayProperty=fullName> implementiert, dann ist der Standardvergleich die <xref:System.IComparable%601.CompareTo%28%600%29?displayProperty=fullName> -Methode dieser Schnittstelle.

  • Wenn Typ T die nicht generische Schnittstelle <xref:System.IComparable?displayProperty=fullName> implementiert, dann ist der Standardvergleich die <xref:System.IComparable.CompareTo%28System.Object%29?displayProperty=fullName> -Methode dieser Schnittstelle.

  • Wenn Typ T keine der Schnittstellen implementiert, gibt es keinen Standardvergleich, und ein Vergleich oder ein Vergleichsdelegat muss explizit angegeben werden.

Um explizite Vergleiche zu ermöglichen, akzeptieren einige Methoden eine IComparer -Implementierung als Parameter. Beispiel: Die <xref:System.Collections.Generic.List%601.Sort%2A?displayProperty=fullName> -Methode akzeptiert eine <xref:System.Collections.Generic.IComparer%601?displayProperty=fullName> -Implementierung.

Die aktuelle Kultureinstellung des Systems kann sich auf die Vergleichs- und Sortiervorgänge innerhalb einer Auflistung auswirken. Standardmäßig sind die Vergleichs- und Sortiervorgänge in den Auflistungen -Klassen kulturabhängig. Um die Kultureinstellung zu ignorieren und daher konsistente Vergleichs- und Sortierergebnisse zu erhalten, verwenden Sie <xref:System.Globalization.CultureInfo.InvariantCulture%2A> mit Memberüberladungen, die <xref:System.Globalization.CultureInfo>akzeptieren. Weitere Informationen finden Sie unter Performing Culture-Insensitive String Operations in Collections und Performing Culture-Insensitive String Operations in Arrays.

Beispiel für Gleichheit und Sortierung

Der folgende Code zeigt eine Implementierung von <xref:System.IEquatable%601> und <xref:System.IComparable%601> für ein einfaches Geschäftsobjekt. Wenn das Objekt in einer Liste gespeichert und sortiert wird, sehen Sie darüber hinaus, dass durch den Aufruf der <xref:System.Collections.Generic.List%601.Sort>-Methode der Standardvergleich für den Part-Typ verwendet wird und die <xref:System.Collections.Generic.List%601.Sort%28System.Comparison%7B%600%7D%29>-Methode mit einer anonymen Methode implementiert wird.

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

Siehe auch

<xref:System.Collections.IComparer>
<xref:System.IEquatable%601>
<xref:System.Collections.Generic.IComparer%601>
<xref:System.IComparable>
<xref:System.IComparable%601>