
- •Введение
- •Сравнение языков С++ и C#
- •Логические выражения
- •Функции для ввода и вывода в языке C#
- •Управление форматом числовых данных:
- •Обработка исключительных ситуаций
- •Методы и модификаторы параметров
- •Неявно типизированные переменные
- •Понятие класса
- •Свойства
- •Индексаторы
- •Одномерные индексаторы
- •Многомерные индексаторы
- •Перегрузка методов
- •Перегрузка знаков операций
- •Наследование
- •Виртуальные функции
- •Работа с файлами
- •Работа с каталогами
- •Абстрактный класс FileSystemInfo
- •Класс DirectoryInfo
- •Сериализация
- •FileSystemWatcher – отслеживание событий, связанных с файлами
- •Обобщения (шаблоны)
- •Интерфейсы
- •Коллекции
- •LINQ
- •Грамматика выражений запросов
- •Синтаксис запросов
- •Проекция и фильтрация
- •Упорядочение
- •Агрегирующие запросы
- •Операции с коллекциями
- •Операция Concat
- •Операция Union
- •Преобразование
- •Объединение последовательностей
- •FirstOrDefault
- •Группировка
- •Групповая адресация
- •Обработка событий
- •Групповое преобразование делегируемых методов
- •Применение методов экземпляра в качестве делегатов
- •Групповая адресация
- •Ковариантность и контравариантность
- •Класс System. Delegate
- •Назначение делегатов
- •Анонимные функции
- •Анонимные методы
- •Передача аргументов анонимному методу
- •Возврат значения из анонимного метода
- •Применение внешних переменных в анонимных методах
- •Лямбда-выражения
- •Лямбда-оператор
- •Одиночные лямбда-выражения
- •Блочные лямбда-выражения
- •События
- •Пример групповой адресации события
- •Применение аксессоров событий
- •Разнообразные возможности событий
- •Применение анонимных методов и лямбда-выражений вместе с событиями
- •Рекомендации по обработке событий в среде .NET Framework
- •Применение делегатов EventHandler<TEventArgs> и EventHandler
- •Практический пример обработки событий

Чернов Э. А. |
- 83 - |
Лекции по языку C# v 2.3 |
Ограничения типа where T: struct и where T: class имеют в виду не конкретный класс или структуру, а только тип. Ограничение where T: new() применяется в случаях, при которых требуется передавать объекты в подпрограммы.
Интерфейсы
Интерфейсом называется класс, содержащий набор абстрактных методов для реализации некоторых действий, обычно, вспомогательных по отношению к основной операции. Абстрактные методы, по определению, реализации не имеют. Они требуют явного переопределения. Применение стандартных интерфейсов предоставляет пользователю полный набор методов для реализации требуемого действия. С другой стороны, компилятор обеспечивает частичную реализацию абстрактных методов.
Интерфейсы бывают обобщенные и необобщенные. В данном разделе рассмотрены необобщенные интерфейсы. Обобщенные интерфейсы будут рассмотрены далее после обобщений вместе с коллекциями.
Рассмотрим интерфейсы, например, для реализации операции сравнения. Сравнить два числа можно, написав логическое отношение, скажем: a > b. Ситуация изменяется, если требуется сравнить два объекта, обладающих рядом атрибутов, которые должны учитываться при сравнении по одному или в некоторой взаимосвязи друг с другом. Характерным примером является выбор для товара лучшего соотношения цены и качества, причем качество, как правило, определяется набор свойств.
Реализации сравнения помогают интерфейсы IComparable и IComparator. (В языке C# принято имена интерфейсов начинать с буквы I). Первый из них задает возможность сравнения текущего объекта (описанного в классе, который наследует интерфейс IComparable) с заданным объектом такого же типа. Интерфейс IComparator позволяет сравнивать два независимых объекта.
Интерфейс IComparable имеет абстрактный метод CompareTo, имеющий формат:
public int CompareTo(<имя класса> obj) // Пример записи
В примере ниже при оформлении метода записан параметр общего класса object, от которого наследуются все классы. Затем объект этого класса преобразуется в локальный объект основного класса (b = (shirt) obj;). Это сделано для того, чтобы можно было сравнивать два соседних элемента в списке, один из которых текущий (слева от знака равенства), а другой следующий в списке (передается как параметр).

Чернов Э. А. |
- 84 - |
Лекции по языку C# v 2.3 |
Метод CompareTo возвращает целое число, указывающее на соотношение между объектами, как указано в таблице. Это число указывает на порядок следования объектов друг за другом, позволяя гибко устанавливать порядок сортировки:
Возвращаемое |
Смысл |
|
число |
||
|
Меньше нуля Данный объект меньше объекта, заданного в виде параметра.
Нуль |
Данный объект и объект, заданный в виде параметра, равны. |
Больше нуля. Данный объект больше объекта, заданного в виде параметра.
Ниже приведена программа, в которой формируется список рубашек. Для рубашки задано всего 3 атрибута: фасон, размер и цена. Листинг программы для реализации сортировки рубашек по цене.
// Программа для иллюстрации необобщенного интерфейса IComparable. class shirt : IComparable
{
int size; |
// Размер |
string fashion; |
// Фасон |
int price; |
// Цена |
public shirt( string f, int p, int s) // Конструктор с параметрами
{
size = s; fashion = f; price = p;
}
public string Fash // Свойство для фасона
{
get { return fashion; } set { fashion = value; }
}
public int Price // Свойство для цены
{
get { return price; } set { price = value; }
}
public int Size // Свойство для размера
{
get { return size; } set { size = value; }
}
// Реализация метода CompareTo для интерфейса IComparable. public int CompareTo(object obj)
{
shirt b; |
// Объявление локального объекта |
b = (shirt) obj; |
// Приведение типа |
int n = price.CompareTo(b.price); // Выполнение сравнения

Чернов Э. А. |
- 85 - |
Лекции по языку C# v 2.3 |
return n;
}
}
class IComparableDemo
{
static void Main()
{
ArrayList sh = new ArrayList(); // Объявление пустого списка
// Формирование списка.
sh.Add(new shirt("Libera Vita", 2250, 44)); sh.Add(new shirt("Broadway", 1760, 42)); sh.Add(new shirt("Sela", 1000, 48)); sh.Add(new shirt("Selected Homme", 2570, 48));
Console.WriteLine("Список рубашек до сортировки:"); foreach (shirt ob in sh)
Console.WriteLine("Фасон {0,-15} Стоимость: {1,4:D} Размер: {2}", ob.Fash, ob.Price, ob.Size);
// Сортировка списка с помощью встроенного метода. sh.Sort();
Console.WriteLine("\n Список рубашек после сортировки по цене:"); foreach (shirt ob in sh)
Console.WriteLine("Фасон {0,-15} Стоимость: {1,4:D} Размер: {2}", ob.Fash, ob.Price, ob.Size);
Console.ReadKey();
}
}
Ниже приведен результат выполнения программы.
Если в методе CompareTo заменить строку выполнения сравнения:
int n = price.CompareTo(b.price); // Выполнение сравнения
строкой, приведенной ниже (а также заменить текст заголовка таблицы после сортировки), то произойдет сортировка по фасону
int n = fashion.CompareTo(b.fashion);

Чернов Э. А. |
- 86 - |
Лекции по языку C# v 2.3 |
Результат будет таким: |
|
|
Способы выбора режима сортировки во время выполнения программы будут рассмотрены далее.
Для сравнения можно применять обобщенные интерфейсы IComparable<T> и IComparer<T>. Как следует из названия, интерфейс IComparable<T> предусматривает возможность выполнения сравнения. Интерфейс IComparable<T>, когда T определен, позволяет сравнивать текущий объект (объект описан в том же классе, в котором выполняется сравнение) с другим объектом того же типа. Интерфейс IComparer<T> (дословно «сравниватель») используется для сравнения двух объектов T, обычно вне самих объектов T. Таким образом, объявление:
class MyClass : IComparable<T>
Вряд ли имеет смысл, поскольку MyClass и T не связаны друг с другом. С другой стороны запись ниже показывает, как это следует делать:
class T : IComparable<T>
{
public int CompareTo(T other) // Сравнить с другим
{
// Операторы для выполнения сравнения...
}
}
Интерфейс IComparer<T> может быть полезен, когда требуется выполнить сортировку, задавая определенный пользователем порядок следования объектов. Например, класс Product можно сортировать по цене (основной порядок следования элементов), но можно сортировать и по названию товара. Это можно выполнить так:
public class Product: IComparable <Product>
{
public string Name { get; set; } public int Price { get; set; } public Product() { } //
// Реализация метода CompareTo (по цене) для интерфейса IComparable. public int CompareTo(Product obj)
{
Чернов Э. А. |
- 87 - |
Лекции по языку C# v 2.3 |
Product b; |
// Объявление локального объекта |
b = (Product)obj; |
// Приведение типа |
int n = Price.CompareTo(b.Price); // Выполнение сравнения return n;
}
}
//Сравнение товаров по названию (класс задает сравнение по названию)
//имя NameComparer может быть любым Правка, где NameComparer? public class: IComparer<Product>
{
//Вызов общего метода сравнения
public int Compare(Product a, Product b)
{
if (a.Name.CompareTo(b.Name) != 0)
{// Переключение метода сравнения CompareTo на название товара return a.Name.CompareTo(b.Name);
}
else return 0;
}
}
class Program
{
static void Main(string[] args)
{
List<Product> lstProd = new List<Product>()
{
new Product{Name="Пицца",Price=83}, new Product{Name="Багет", Price=65}, new Product{Name="Пирог",Price=35}, new Product{Name="Орбит",Price=25}, new Product{Name="Фанта",Price=48}, new Product{Name="Пепси",Price=88}
};
Console.WriteLine("Исходный массив"); foreach (Product prod in lstProd)
Console.WriteLine("{0} \t{1}",prod.Name, prod.Price);
//Сортировка по умолчанию, определено методом CompareTo lstProd.Sort();
Console.WriteLine("\nПосле сортировки по цене"); foreach (Product prod in lstProd)
Console.WriteLine("{0} \t{1}",prod.Name, prod.Price);
//Изменение порядка сортировки интерфейсом IComparer Console.WriteLine("\n После сортировки по названию"); NameComparer pc = new NameComparer();
lstProd.Sort();
foreach (Product prod in lstProd) Console.WriteLine("{0} \t{1}",prod.Name, prod.Price);
Console.ReadKey();
}
}