Użycie interfejsu IComparer w C# - przykład

Potrzebne elementy są w przestrzeni nazw System.Collections.Generic;

using System.Collections.Generic;

Przykład bazuje na klasie implementującej interfejs:

  interface ITowar
  {
    string Nazwa { get; set; }
    double Cena { get; set; }
    int IloscWMagazynie { get; set; }
  }

Implementacja tej klasy:

  class Towar : ITowar
  {
    public string ID { get; set; }
    public string Nazwa { get; set; }
    public double Cena { get; set; }
    public int IloscWMagazynie { get; set; }
    public override string ToString()
    {
      return string.Format("{0} {1,-10} {2,5:F2} {3,4}", ID, Nazwa, Cena, IloscWMagazynie);
    }
  }

Do przechowywania i zarządzania kolekcją obiektów ITowar wykorzystana zostanie tzw. lista generyczna:

  List<ITowar> lista = new List<ITowar>();

Klasa Lista posiada metodę Sort, która będzie wymagać parametru w postaci obiektu implementującego interfejs IComparer<ITowar>.

Zadanie polega na przygotowaniu trzech klas implementujących interfejs IComparer<ITowar>, które umożliwią sortowanie listy towarów na trzy sposoby. Dwa sortowania wg pojedynednego kryterium: wg nazwy, wg ceny. Oraz sortowanie nieco bardziej zaawansowane wg nazwy oraz wg ceny.

Oto one:

  class WgNazwy : IComparer<ITowar>
  {
    public int Compare(ITowar x, ITowar y)
    {
      return string.Compare(x.Nazwa, y.Nazwa);
    }
  }
  class WgCeny : IComparer<ITowar>
  {
    public int Compare(ITowar x, ITowar y)
    {     
      if (x.Cena < y.Cena) return -1;
      else if (x.Cena > y.Cena) return 1;
      else return 0;
    }
  }
  class WgNazawy_i_Ceny : IComparer<ITowar>
  {
    public int Compare(ITowar x, ITowar y)
    {      
      int si = string.Compare(x.Nazwa, y.Nazwa);
      if (si == 0)
      {
        if (x.Cena < y.Cena) return -1;
        else if (x.Cena > y.Cena) return 1;
        else return 0;
      }
      else
        return si;
    }
  }

Do testowania można przygotować formularz z trzema przyciskami Button i jedną kontrolką typu ListBox.

W kodzie formularza zadeklarowano pole:

   
   List<ITowar> lista = new List<ITowar>();

... oraz pomocniczo:

   Random rnd = new Random();
   string[] towary = new string[] { "Chleb", "Bułka", "Masło", "Makaron", "Konserwa" };   

Pierwszy przycisk służy do zainicjowania listy towarów i jej prezentacji w kontrolce ListBox:

   private void btnLosuj_Click(object sender, EventArgs e)
    {
      listBox1.DataSource = null;
      lista.Clear();
      for (int i = 0; i < 15; i++)
      {
        string aID = (i + 1).ToString("d5");
        string aNazwa = towary[rnd.Next(towary.Length)];
        double aCena = Math.Round(5 + 10 * rnd.NextDouble(), 2);
        int aIlosc = 1 + rnd.Next(100);
        ITowar t = new Towar() { ID = aID, Nazwa = aNazwa, Cena = aCena, IloscWMagazynie = aIlosc };
        lista.Add(t);
      }
      listBox1.DataSource = lista;
    }  

Pozostałe przyciski służą do wykonania odpowiedniego sortowania prezentacji wyniku w kontrolce ListBox:

   private void btnWgNazwy_Click(object sender, EventArgs e)
    {
      listBox1.DataSource = null;
      lista.Sort(new WgNazwy());
      listBox1.DataSource = lista;
    }

    private void btnWgCeny_Click(object sender, EventArgs e)
    {
      listBox1.DataSource = null;
      lista.Sort(new WgCeny());
      listBox1.DataSource = lista;
    }

    private void btnWgNazwy_i_Ceny_Click(object sender, EventArgs e)
    {
      listBox1.DataSource = null;
      lista.Sort(new WgNazawy_i_Ceny());
      listBox1.DataSource = lista;
    }