Сортировка по разным критериям (интерфейс IComparer) — КиберПедия 

Состав сооружений: решетки и песколовки: Решетки – это первое устройство в схеме очистных сооружений. Они представляют...

Наброски и зарисовки растений, плодов, цветов: Освоить конструктивное построение структуры дерева через зарисовки отдельных деревьев, группы деревьев...

Сортировка по разным критериям (интерфейс IComparer)

2019-09-26 234
Сортировка по разным критериям (интерфейс IComparer) 0.00 из 5.00 0 оценок
Заказать работу

Интерфейс IComparer определен в пространстве имен System.Collections. Он содержит один метод Compare, возвращающий результат сравнения двух объектов, переданных ему в качестве параметров:

interface IComparer

{

int Compare(object ob1, object ob2)

}

Принцип применения этого интерфейса состоит в том, что для каждого критерия сортировки объектов описывается небольшой вспомогательный класс, реализующий этот интерфейс. Объект этого класса передается в стандартный метод сортировки массива в качестве второго аргумента.

Пример сортировки массива объектов из предыдущего листинга по именам (свойство Name, класс SortByName) и количеству вооружений (свойство Ammo, класс SortByAmmo) приведен в листинге 2.

using System;

using System.Collections;

namespace ConsoleApplication1

{

class Monster

{

   public Monster(int health, int ammo, string name)

   {

       this.health = health;

       this.ammo = ammo;

       this.name = name;

   }

       

   public int Ammo

   {

       get { return ammo; }

       set

       {

           if (value > 0) ammo = value;

           else      ammo = 0;

       }

   }

   public string Name

   {

       get { return name; }

   }

   virtual public void Passport()

   {

       Console.WriteLine("Monster {0} \t health = {1} ammo = {2}",

                          name, health, ammo);

   }

   public class SortByName: IComparer                          //

   {

       int IComparer.Compare(object ob1, object ob2)

       {

           Monster m1 = (Monster) ob1;

           Monster m2 = (Monster) ob2;

           return String.Compare(m1.Name, m2.Name);

       }

   }

   public class SortByAmmo: IComparer                          //

   {

       int IComparer.Compare(object ob1, object ob2)

       {

           Monster m1 = (Monster) ob1;

           Monster m2 = (Monster) ob2;

           if (m1.Ammo > m2.Ammo) return 1;

           if (m1.Ammo < m2.Ammo) return -1;

           return 0;

       }

   }

   string name;

   int health, ammo;

}

   

class Class1

{ static void Main()

   {

       const int n = 3;

       Monster[] stado = new Monster[n];

       stado[0] = new Monster(50, 50, "Вася");

       stado[1] = new Monster(80, 80, "Петя");

       stado[2] = new Monster(40, 10, "Маша");

       Console.WriteLine("Сортировка по имени:");

       Array.Sort(stado, new Monster.SortByName());

       foreach (Monster elem in stado) elem.Passport();

       Console.WriteLine("Сортировка по вооружению:");

       Array.Sort(stado, new Monster.SortByAmmo());

       foreach (Monster elem in stado) elem.Passport();

   }

}

}

Листинг 2. Сортировка по двум критериям

Результат работы программы:

Сортировка по имени:

Monster Вася health = 50 ammo = 50

Monster Маша health = 40 ammo = 10

Monster Петя health = 80 ammo = 80

Сортировка по вооружению:

Monster Маша health = 40 ammo = 10

Monster Вася health = 50 ammo = 50

Monster Петя health = 80 ammo = 80

Перегрузка операций отношения

Если класс реализует интерфейс IComparable, его экземпляры можно сравнивать между собой на больше-меньше. Логично разрешить использовать для этого операции отношения, перегрузив их. Операции должны перегружаться парами: < и >, <= и >=, == и!=. Перегрузка операций обычно выполняется путем делегирования, то есть обращения к переопределенным методам CompareTo и Equals.

Обязательно

Если класс реализует интерфейс IComparable, требуется переопределить метод Equals и связанный с ним метод GetHashCode. Оба метода унаследованы от базового класса object.

В листинге 3 операции отношения перегружены для класса Monster. В качестве критерия сравнения объектов на больше-меньше выступает поле health, а при сравнении на равенство попарно сравниваются все поля объектов

using System;

namespace ConsoleApplication1

{

class Monster: IComparable

{

   public Monster(int health, int ammo, string name)

   {

       this.health = health;

       this.ammo = ammo;

       this.name = name;

   }

   public override bool Equals(object obj)

   {

       if (obj == null || GetType()!= obj.GetType()) return false;

       Monster temp = (Monster) obj;

       return health == temp.health &&

              ammo == temp.ammo &&

              name == temp.name;

   }

   public override int GetHashCode()

   {

       return name.GetHashCode();

   }

   public static bool operator == (Monster a, Monster b)

   {

       return a.Equals(b);

   }

   public static bool operator!= (Monster a, Monster b)

   {

       return! a.Equals(b);

   }

   public static bool operator < (Monster a, Monster b)

   {

       return (a.CompareTo(b) < 0);

   }

       

   public static bool operator > (Monster a, Monster b)

   {

       return (a.CompareTo(b) > 0);

   }

       

   public static bool operator <= (Monster a, Monster b)

   {

       return (a.CompareTo(b) <= 0);

   }

       

   public static bool operator >= (Monster a, Monster b)

   {

       return (a.CompareTo(b) >= 0);

   }

   public int CompareTo(object obj)

   {

       Monster temp = (Monster) obj;

       if (this.health > temp.health) return 1;

       if (this.health < temp.health) return -1;

       return 0;

   }

   string name;

   int health, ammo;

}

class Class1

{ static void Main()

   {

       Monster Вася = new Monster(70, 80, "Вася");

       Monster Петя = new Monster(80, 80, "Петя");

       

       if (Вася > Петя) Console.WriteLine("Вася больше Пети");

      else if (Вася == Петя) Console.WriteLine("Вася == Петя");

       else                Console.WriteLine("Вася меньше Пети");

   }

}

}

Листинг 3. Перегрузка операций отношения

Результат работы программы:

Вася меньше Пети

Клонирование объектов

Клонирование — это создание копии объекта. Копия объекта называется клоном. Как известно, при присваивании одного объекта ссылочного типа другому копируется ссылка, а не сам объект. Если необходимо скопировать в другую область памяти поля объекта, можно воспользоваться методом MemberwiseClone, который любой объект наследует от класса object. При этом объекты, на которые указывают поля объекта, в свою очередь являющиеся ссылками, не копируются. Это называется поверхностным клонированием.

Для создания полностью независимых объектов необходимо глубокое клонирование, когда в памяти создается дубликат всего дерева объектов, то есть объектов, на которые ссылаются поля объекта, поля полей, и так далее. Алгоритм глубокого клонирования весьма сложен, поскольку требует рекурсивного обхода всех ссылок объекта и отслеживания циклических зависимостей.

Объект, имеющий собственные алгоритмы клонирования, должен объявляться как наследник интерфейса ICloneable и переопределять его единственный метод Clone. В листинге 9.4 приведен пример создания поверхностной копии объекта класса Monster с помощью метода MemberwiseClone, а также реализован интерфейс ICloneable. В демонстрационных целях в имя клона объекта добавлено слово "Клон".

using System;

namespace ConsoleApplication1

{

class Monster: ICloneable

{

   public Monster(int health, int ammo, string name)

   {

       this.health = health;

       this.ammo = ammo;

       this.name = name;

   }

   public Monster ShallowClone()            // поверхностная копия

   {

       return (Monster)this.MemberwiseClone();

   }

   public object Clone()                 // пользовательская копия

   {

       return new Monster(this.health, this.ammo, "Клон " + this.name);

   }

 

   virtual public void Passport()

   {

       Console.WriteLine("Monster {0} \t health = {1} ammo = {2}",

                          name, health, ammo);

   }

   string name;

   int health, ammo;

}

       

class Class1

{ static void Main()

   {

         Monster Вася = new Monster(70, 80, "Вася");

       Monster X = Вася;

       Monster Y = Вася.ShallowClone();

       Monster Z = (Monster)Вася.Clone();

      ...

   }

}

}

Листинг 4. Клонирование объектов

Объект Х ссылается на ту же область памяти, что и объект Вася. Следовательно, если мы внесем изменения в один из этих объектов, это отразится на другом. Объекты Y и Z, созданные путем клонирования, обладают собственными копиями значений полей и независимы от исходного объекта.


Поделиться с друзьями:

Механическое удерживание земляных масс: Механическое удерживание земляных масс на склоне обеспечивают контрфорсными сооружениями различных конструкций...

Организация стока поверхностных вод: Наибольшее количество влаги на земном шаре испаряется с поверхности морей и океанов (88‰)...

Таксономические единицы (категории) растений: Каждая система классификации состоит из определённых соподчиненных друг другу...

Семя – орган полового размножения и расселения растений: наружи у семян имеется плотный покров – кожура...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.005 с.