Verwenden der IComparable Schnittstellen und IComparer in Visual CSharp

In diesem Artikel wird die Verwendung von IComparer - und IComparable -Schnittstellen in Visual C# beschrieben.

Ursprüngliche Produktversion: Visual C#
Ursprüngliche KB-Nummer: 320727

Zusammenfassung

Die IComparable Schnittstellen und IComparer werden aus zwei Gründen im selben Artikel erläutert. Diese Schnittstellen werden häufig zusammen verwendet. Obwohl die Schnittstellen ähnlich sind und ähnliche Namen haben, dienen sie unterschiedlichen Zwecken.

Wenn Sie über ein Array von Typen verfügen (z. B. Zeichenfolge oder ganze Zahl), die bereits unterstützen IComparer, können Sie dieses Array sortieren, ohne einen expliziten Verweis auf bereitzustellen IComparer. In diesem Fall werden die Elemente des Arrays für Sie in die Standardimplementierung von IComparer (Comparer.Default) umgewandelt. Wenn Sie jedoch eine Sortier- oder Vergleichsfunktion für Ihre benutzerdefinierten Objekte bereitstellen möchten, müssen Sie eine oder beide dieser Schnittstellen implementieren.

In diesem Artikel wird auf den Microsoft .NET Framework-Klassenbibliotheksnamespace verwiesenSystem.Collections.

IComparable

Die Rolle von IComparable besteht darin, eine Methode zum Vergleichen von zwei Objekten eines bestimmten Typs bereitzustellen. Dies ist erforderlich, wenn Sie eine Bestellfunktion für Ihr Objekt bereitstellen möchten. IComparable Stellen Sie sich vor, eine Standardsortierreihenfolge für Ihre Objekte bereitzustellen. Wenn Sie beispielsweise über ein Array von Objekten Ihres Typs verfügen und die Sort -Methode für dieses Array aufrufen, IComparable stellt den Vergleich der Objekte während der Sortierung bereit. Wenn Sie die IComparable -Schnittstelle implementieren, müssen Sie die CompareTo -Methode wie folgt implementieren:

// Implement IComparable CompareTo method - provide default sort order.
int IComparable.CompareTo(object obj)
{
   Car c=(Car)obj;
   return String.Compare(this.make,c.make);
}

Der Vergleich in der -Methode unterscheidet sich je nach Datentyp des zu vergleichenden Werts. String.Compare wird in diesem Beispiel verwendet, da die Eigenschaft, die für den Vergleich ausgewählt wird, eine Zeichenfolge ist.

IComparer

Die Rolle von IComparer besteht darin, weitere Vergleichsmechanismen bereitzustellen. Sie können z. B. die Reihenfolge ihrer Klasse für mehrere Felder oder Eigenschaften, die aufsteigende und absteigende Reihenfolge für dasselbe Feld oder beides angeben.

Die Verwendung von IComparer ist ein zweistufiger Prozess. Deklarieren Sie zunächst eine Klasse, die IComparerimplementiert, und implementieren Sie dann die Compare -Methode:

private class SortYearAscendingHelper : IComparer
{
   int IComparer.Compare(object a, object b)
   {
      Car c1=(Car)a;
      Car c2=(Car)b;
      if (c1.year > c2.year)
         return 1;
      if (c1.year < c2.year)
         return -1;
      else
         return 0;
   }
}

Hinweis

Die IComparer.Compare -Methode erfordert einen tertiären Vergleich. 1, 0 oder -1 wird zurückgegeben, je nachdem, ob ein Wert größer, gleich oder kleiner als der andere ist. Die Sortierreihenfolge (aufsteigend oder absteigend) kann durch Wechseln der logischen Operatoren in dieser Methode geändert werden.

Der zweite Schritt besteht darin, eine Methode zu deklarieren, die eine instance Ihres IComparer Objekts zurückgibt:

public static IComparer SortYearAscending()
{
   return (IComparer) new SortYearAscendingHelper();
}

In diesem Beispiel wird das -Objekt als zweites Argument verwendet, wenn Sie die überladene Array.Sort Methode aufrufen, die akzeptiert IComparer. Die Verwendung von IComparer ist nicht auf Arrays beschränkt. Es wird als Argument in vielen verschiedenen Auflistungs- und Steuerelementklassen akzeptiert.

Schritt-für-Schritt-Beispiel

Im folgenden Beispiel wird die Verwendung dieser Schnittstellen veranschaulicht. Zur Veranschaulichen IComparer von und IComparablewird eine Klasse mit dem Namen Car erstellt. Das Car -Objekt verfügt über die Eigenschaften make und year. Eine aufsteigende Sortierung für das Make-Feld wird über die IComparable -Schnittstelle aktiviert, und eine absteigende Sortierung für das Make-Feld wird über die IComparer -Schnittstelle aktiviert. Sowohl aufsteigende als auch absteigende Sortierungen werden für die Year-Eigenschaft mithilfe IComparervon bereitgestellt.

  1. Erstellen Sie in Visual C# ein neues Konsolenanwendungsprojekt. Nennen Sie die Anwendung ConsoleEnum.

  2. Benennen Sie Program.cs in Host.cs um, und ersetzen Sie den Code dann durch den folgenden Code.

    using System;
    
    namespace ConsoleEnum
    {
        class host
        {
           [STAThread]
           static void Main(string[] args)
           {
              // Create an array of Car objects.
              Car[] arrayOfCars= new Car[6]
              {
                 new Car("Ford",1992),
                 new Car("Fiat",1988),
                 new Car("Buick",1932),
                 new Car("Ford",1932),
                 new Car("Dodge",1999),
                 new Car("Honda",1977)
              };
    
              // Write out a header for the output.
              Console.WriteLine("Array - Unsorted\n");
    
              foreach(Car c in arrayOfCars)
                 Console.WriteLine(c.Make + "\t\t" + c.Year);
    
              // Demo IComparable by sorting array with "default" sort order.
              Array.Sort(arrayOfCars);
              Console.WriteLine("\nArray - Sorted by Make (Ascending - IComparable)\n");
    
              foreach(Car c in arrayOfCars)
                 Console.WriteLine(c.Make + "\t\t" + c.Year);
    
              // Demo ascending sort of numeric value with IComparer.
              Array.Sort(arrayOfCars,Car.SortYearAscending());
              Console.WriteLine("\nArray - Sorted by Year (Ascending - IComparer)\n");
    
              foreach(Car c in arrayOfCars)
                 Console.WriteLine(c.Make + "\t\t" + c.Year);
    
              // Demo descending sort of string value with IComparer.
              Array.Sort(arrayOfCars,Car.SortMakeDescending());
              Console.WriteLine("\nArray - Sorted by Make (Descending - IComparer)\n");
    
              foreach(Car c in arrayOfCars)
                 Console.WriteLine(c.Make + "\t\t" + c.Year);
    
              // Demo descending sort of numeric value using IComparer.
              Array.Sort(arrayOfCars,Car.SortYearDescending());
              Console.WriteLine("\nArray - Sorted by Year (Descending - IComparer)\n");
    
              foreach(Car c in arrayOfCars)
                 Console.WriteLine(c.Make + "\t\t" + c.Year);
    
              Console.ReadLine();
           }
       }
    }
    
  3. Fügen Sie dem Projekt eine Klasse hinzu. Nennen Sie die Klasse Car.

  4. Ersetzen Sie den Code in Car.cs durch den folgenden Code:

    using System;
    using System.Collections;
    namespace ConsoleEnum
    {
       public class Car : IComparable
       {
          // Beginning of nested classes.
          // Nested class to do ascending sort on year property.
          private class SortYearAscendingHelper: IComparer
          {
             int IComparer.Compare(object a, object b)
             {
                Car c1=(Car)a;
                Car c2=(Car)b;
    
                if (c1.year > c2.year)
                   return 1;
    
                if (c1.year < c2.year)
                   return -1;
    
                else
                   return 0;
             }
          }
    
          // Nested class to do descending sort on year property.
          private class SortYearDescendingHelper: IComparer
          {
             int IComparer.Compare(object a, object b)
             {
                Car c1=(Car)a;
                Car c2=(Car)b;
    
                if (c1.year < c2.year)
                   return 1;
    
                if (c1.year > c2.year)
                   return -1;
    
                else
                   return 0;
             }
          }
    
          // Nested class to do descending sort on make property.
          private class SortMakeDescendingHelper: IComparer
          {
             int IComparer.Compare(object a, object b)
             {
                Car c1=(Car)a;
                Car c2=(Car)b;
                 return String.Compare(c2.make,c1.make);
             }
          }
          // End of nested classes.
          private int year;
          private string make;
    
          public Car(string Make,int Year)
          {
             make=Make;
             year=Year;
          }
    
          public int Year
          {
             get  {return year;}
             set {year=value;}
          }
    
          public string Make
          {
             get {return make;}
             set {make=value;}
          }
          // Implement IComparable CompareTo to provide default sort order.
          int IComparable.CompareTo(object obj)
          {
             Car c=(Car)obj;
             return String.Compare(this.make,c.make);
          }
          // Method to return IComparer object for sort helper.
          public static IComparer SortYearAscending()
          {
             return (IComparer) new SortYearAscendingHelper();
          }
          // Method to return IComparer object for sort helper.
          public static IComparer SortYearDescending()
          {
             return (IComparer) new SortYearDescendingHelper();
          }
          // Method to return IComparer object for sort helper.
          public static IComparer SortMakeDescending()
          {
            return (IComparer) new SortMakeDescendingHelper();
          }
    
       }
    }
    
  5. Führen Sie das Projekt aus. Die folgende Ausgabe wird im Konsolenfenster angezeigt:

    Array - Unsorted
    
    Ford 1992
    Fiat 1988
    Buick 1932
    Ford 1932
    Dodge 1999
    Honda 1977
    
    Array - Sorted by Make (Ascending - IComparable)
    
    Buick 1932
    Dodge 1999
    Fiat 1988
    Ford 1932
    Ford 1992
    Honda 1977
    
    Array - Sorted by Year (Ascending - IComparer)
    
    Ford 1932
    Buick 1932
    Honda 1977
    Fiat 1988
    Ford 1992
    Dodge 1999
    
    Array - Sorted by Make (Descending - IComparer)
    
    Honda 1977
    Ford 1932
    Ford 1992
    Fiat 1988
    Dodge 1999
    Buick 1932
    
    Array - Sorted by Year (Descending - IComparer)
    
    Dodge 1999
    Ford 1992
    Fiat 1988
    Honda 1977
    Buick 1932
    Ford 1932