Udostępnij za pośrednictwem


IComparable Używanie interfejsów i IComparer w programie Visual CSharp

W tym artykule opisano użycie interfejsów IComparer i IComparable w języku Visual C#.

Oryginalna wersja produktu: Visual C#
Oryginalny numer KB: 320727

Podsumowanie

Interfejsy IComparable i IComparer zostały omówione w tym samym artykule z dwóch powodów. Te interfejsy są często używane razem. Mimo że interfejsy są podobne i mają podobne nazwy, służą one różnym celom.

Jeśli masz tablicę typów (takich jak ciąg lub liczba całkowita), które już obsługują IComparer, możesz sortować tablicę bez podawania jawnego odwołania do IComparer. W takim przypadku elementy tablicy są rzutowane do domyślnej implementacji IComparer (Comparer.Default). Jeśli jednak chcesz zapewnić możliwość sortowania lub porównywania dla obiektów niestandardowych, musisz zaimplementować jeden lub oba te interfejsy.

W tym artykule odwołuje się do przestrzeni System.Collectionsnazw biblioteki klas programu Microsoft .NET Framework.

IComparable

Rolą IComparable obiektu jest zapewnienie metody porównywania dwóch obiektów określonego typu. Jest to konieczne, jeśli chcesz udostępnić dowolną możliwość porządkowania dla obiektu. Pomyśl o IComparable dostarczaniu domyślnej kolejności sortowania dla obiektów. Jeśli na przykład masz tablicę obiektów typu i wywołasz Sort metodę w tej tablicy, IComparable zapewnia porównanie obiektów podczas sortowania. Podczas implementowania interfejsu IComparable należy zaimplementować metodę CompareTo w następujący sposób:

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

Porównanie metody różni się w zależności od typu danych porównywanej wartości. String.Compare Jest używany w tym przykładzie, ponieważ właściwość wybrana dla porównania jest ciągiem.

IComparer

Rolą programu jest zapewnienie większej IComparer liczby mechanizmów porównywania. Na przykład możesz podać kolejność klasy w kilku polach lub właściwościach, kolejności rosnącej i malejącej w tym samym polu lub obu tych polach.

Użycie IComparer jest procesem dwuetapowym. Najpierw zadeklaruj klasę, która implementuje IComparermetodę , a następnie zaimplementuj metodę Compare :

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

Uwaga 16.

Metoda IComparer.Compare wymaga porównania tertiary. Zwracana jest wartość 1, 0 lub -1 w zależności od tego, czy jedna wartość jest większa niż, równa, czy mniejsza niż druga. Kolejność sortowania (rosnąco lub malejąco) można zmienić, przełączając operatory logiczne w tej metodzie.

Drugim krokiem jest zadeklarowanie metody zwracającej IComparer wystąpienie obiektu:

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

W tym przykładzie obiekt jest używany jako drugi argument podczas wywoływania metody przeciążonej Array.Sort , która akceptuje IComparerelement . Użycie elementu IComparer nie jest ograniczone do tablic. Jest akceptowany jako argument w wielu różnych klasach kolekcji i kontrolek.

Przykład krok po kroku

W poniższym przykładzie pokazano użycie tych interfejsów. Aby zademonstrować IComparer i IComparable, zostanie utworzona klasa o nazwie Car . Obiekt Car ma właściwości make i year. Sortowanie rosnące dla pola make jest włączone za pośrednictwem interfejsu IComparable , a sortowanie malejące w polu make jest włączone za pośrednictwem interfejsu IComparer . Zarówno sortowania rosnącego, jak i malejącego są udostępniane dla właściwości year przy użyciu polecenia IComparer.

  1. W programie Visual C# utwórz nowy projekt aplikacja konsolowa. Nadaj aplikacji nazwę ConsoleEnum.

  2. Zmień nazwę Program.cs na Host.cs, a następnie zastąp kod poniższym kodem.

    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. Dodaj klasę do projektu. Nadaj klasie nazwę Samochód.

  4. Zastąp kod w Car.cs następującym kodem:

    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. Uruchamianie projektu. Następujące dane wyjściowe są wyświetlane w oknie Konsola :

    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