- •1 Основные сведения о C#
- •1.1 Особенности языка
- •1.2 Типы данных
- •1.3 Переменные
- •1.4 Константы (литералы)
- •1.5 Операторы, используемые при построении выражений
- •1.6 Класс Object
- •1.7 Класс Math
- •1.8 Класс Convert
- •1.9 Пространство имён
- •1.10 Типы, допускающие значение null
- •2 Операторы и конструкции С#
- •2.1 Операторы присваивания
- •2.2 Приведение типов
- •2.3 Операторы инкремента и декремента
- •2.4 Операторные скобки {}
- •2.5 Условный оператор if
- •2.6 Логические операторы «И» и «ИЛИ»
- •2.7 Условный оператор ? :
- •2.8 Оператор выбора switch и оператор прерывания break
- •2.9 Оператор цикла for
- •2.10 Оператор цикла while
- •2.11 Оператор цикла do...while
- •2.12 Операторы прерываний break (для циклов) и continue
- •2.13 Оператор new
- •2.14 Массивы
- •2.14.1 Одномерные массивы
- •2.14.2 Многомерные массивы
- •2.14.3 Ступенчатые массивы
- •2.14.4 Работа с массивами как с объектами
- •2.15 Оператор цикла foreach
- •2.16 Строки
- •2.17 Перечисления
- •2.18 Обработка исключений
- •2.18.1 Класс Exception и стандартные исключения
- •2.18.2 Блок try...catch
- •2.18.3 Блок try...finally
- •2.18.4 Блок try...catch...finally
- •2.18.5 Оператор throw
- •3 Классы. Основные понятия
- •3.1 Общая схема
- •3.2 Спецификаторы доступа
- •3.3 Поля
- •3.4 Создание объекта и доступ к его членам
- •3.5 Методы
- •3.5.1 Перегрузка методов
- •3.5.2 Новое в версии C# 4.0
- •3.6 Конструкторы
- •3.7 Деструкторы
- •3.8 Инициализаторы объектов
- •3.9 Свойства
- •3.10 Индексаторы
- •4 Классы. Расширенное использование
- •4.1 Статические классы и члены классов
- •4.2 Наследование
- •4.2.1 Наследование и конструкторы
- •4.2.2 Переопределение членов класса
- •4.3 Полиморфизм
- •4.3.1 Виртуальные методы
- •4.3.2 Абстрактные классы и члены классов
- •4.3.3 Операторы as и is
- •4.3.4 Модификатор sealed
- •4.4 Перегрузка операторов
- •5 Интерфейсы
- •6 Делегаты, лямбда-выражения и события
- •6.1 Делегаты
- •6.2 Анонимные методы и лямбда-выражения
- •6.3 События
- •7 Универсальные типы
- •7.1 Общая схема
- •7.2 Ограничения по параметрам типа
- •7.2.1 Ограничение на базовый класс
- •7.2.2 Ограничение на интерфейс
- •7.2.3 Ограничение на конструктор
- •7.2.4 Ограничения ссылочного типа и типа значения
- •7.3 Параметры типы в методах
- •7.4 Некоторые универсальные типы С#
- •7.4.1 Класс Array
- •7.4.2 Класс List<T>
- •7.4.3 Класс LinkedList<T>
- •7.4.4 Класс Queue<T>
- •7.4.5 Класс Stack<T>
- •7.4.6 Классы SortedSet<T> и HashSet<T>
- •7.4.7 Классы Dictionary<TKey, TValue> и SortedDictionary<TKey, TValue>
- •8 Работа с файлами
- •8.1 Класс File
- •8.2 Работа с файлами как с потоками
- •8.2.1 Класс FileStream
- •8.2.2 Класс StreamReader
- •8.2.3 Класс StreamWriter
- •8.2.4 Класс BinaryReader
- •8.2.5 Класс BinaryWriter
- •9 LINQ
- •9.1 Программные конструкции и типы, используемые LINQ
- •9.1.1 Методы расширения
- •9.1.2 Анонимные типы
- •9.1.3 Интерфейс IEnumerable<T>
- •9.2 Построение запросов на LINQ
- •9.2.1 Общая структура запроса
- •9.2.2 Простой запрос
- •9.2.3 where : использование условий отбора
- •9.2.4 orderby : использование сортировки
- •9.2.5 select : определение возвращаемого значения
- •9.2.1 group : группировка данных
- •9.2.1 into : обработка результатов группировки
- •9.2.1 let : временные переменные в запросе
- •9.2.2 from : использование нескольких источников данных
- •9.2.3 join : соединение данных из нескольких источников
- •9.3 Получение результатов с использованием методов
- •9.3.1 Метод Where
- •9.3.2 Метод Select
- •9.3.3 Методы сортировки
- •9.3.4 Метод GroupBy
- •9.3.5 Метод Join
- •9.3.6 Дополнительные методы интерфейса IEnumerable<T>
- •9.4 Совместное использование запросов и методов
ЯАП
Смирнов
9.3 Получение результатов с использованием методов
Получением результатов, аналогичных описанным в подразделе 9.2, может быть достигнуто с использованием методов, описанных в интерфейсе IEnumerable<T>1. Фактически, построенный запрос автоматически преобразуется в последовательность вызовов методов данного интерфейса. Соответствие между операторами запроса и методами интерфейса IEnumerable<T> приведено в табли-
це 9.2.
Таблица 9.2 – Соответствие между операторами запроса и методами интер-
фейса IEnumerable<T>
Оператор |
Метод интерфейса |
запроса |
|
select |
Select(selector) |
where |
Where(predicate) |
|
|
orderby |
OrderBy(keySelector) |
|
OrderByDescending(keySelector) |
|
ThenBy(keySelector) |
|
ThenByDescending(keySelector) |
|
|
group |
GroupBy(keySelector) |
|
|
join |
Join(inner, outerKeySelector, innerKeySelector, |
|
resultSelector) |
|
|
Параметры selector, predicate, keySelector, outerKeySelector, innerKeySelector представляют собой реализацию делегата
public delegate TResult Func<in T, out TResult>(T arg)
Параметр resultSelector представляет собой реализацию делегата
public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2)
Реализация делегатов может быть выполнена как методом, так и лямбдавыражением.
1 Некоторые из методов упоминались при рассмотрении интерфейса IEnumerable<T>. В данном подразделе упомянутые ранее методы будут рассмотрены еще раз на основе примеров, использующих пользовательские классы.
162
9.3.1 Метод Where
Метод Where(predicate) используется для отбора из последовательности тех элементов, которые удовлетворяют некоторому условию. Для отбора используется predicate – реализация делегата Func, входным параметром которого является элемент последовательности, а выходным – логическое выражение, определяющее, должен ли учитываться данный элемент.
Пример 1: отобрать людей, родившихся после 1980 года (реализация с помощью лямбда-выражения).
People[] Peoples = new People[6];
Peoples[0] = new People() { Surname = "Иванов", YearOfBirth = 1980, City = "Новокузнецк" };
Peoples[1] = new People() { Surname = "Петров", YearOfBirth = 1999, City = "Москва" };
Peoples[2] = new People() { Surname = "Иванов", YearOfBirth = 1971, City = "Псков" };
Peoples[3] = new People() { Surname = "Степанов", YearOfBirth = 1980, City = "Москва" };
Peoples[4] = new People() { Surname = "Антонов", YearOfBirth = 2001, City = "Новокузнецк" };
Peoples[5] = new People() { Surname = "Попов", YearOfBirth = 1980, City = "Новокузнецк" };
var Result = Peoples.Where(p => p.YearOfBirth > 1980);
// Result = {[Петров, 1999, Москва], [Антонов, 2001, Новокузнецк]}
Пример 2: реализация предыдущего примера с помощью метода.
bool F(People p)
{
return p.YearOfBirth > 1980;
}
var Result = Peoples.Where(F);
//Result = {[Петров, 1999, Москва], [Антонов, 2001, Новокузнецк]}
9.3.2Метод Select
Метод Select(selector) используется для обеспечения вывода элемента последовательности в видоизмененном виде. Для преобразования элемента последовательности используется selector – реализация делегата Func, входным параметром которого является элемент последовательности, а выходным – видоизмененное значение данного элемента.
Пример 1: отобрать фамилии людей, родившихся после 1980 года (реализация с помощью лямбда-выражения).
163
var Result = Peoples.Where(p => p.YearOfBirth > 1980)
.Select(p => p.Surname); // Result = {“Петров”, “Антонов”}
Пример 2: реализация предыдущего примера с помощью метода.
string F(People p)
{
return p.Surname;
}
var Result = Peoples.Where(p => p.YearOfBirth > 1980).Select(F);
//Result = {“Петров”, “Антонов”}
9.3.3Методы сортировки
Метод OrderBy(keySelector) выполняет сортировку по возрастанию, а метод OrderByDescending(keySelector) – по убыванию. Для определения правила сортировки используется keySelector – реализация делегата Func, входным параметром которого является элемент последовательности, а выходным – видоизмененное значение данного элемента, по которому и осуществляется сортировка.
Пример 1: отсортировать людей в алфавитном порядке фамилий (реализация с помощью лямбда-выражения).
People[] Peoples = new People[6];
Peoples[0] = new People() { Surname = "Иванов", YearOfBirth = 1980, City = "Новокузнецк" };
Peoples[1] = new People() { Surname = "Петров", YearOfBirth = 1999, City = "Москва" };
Peoples[2] = new People() { Surname = "Иванов", YearOfBirth = 1971, City = "Псков" };
Peoples[3] = new People() { Surname = "Степанов", YearOfBirth = 1980, City = "Москва" };
Peoples[4] = new People() { Surname = "Антонов", YearOfBirth = 2001, City = "Новокузнецк" };
Peoples[5] = new People() { Surname = "Попов", YearOfBirth = 1980, City = "Новокузнецк" };
var Result = Peoples.OrderBy(p => p.Surname); // Result = {[Антонов, 2001, Новокузнецк],
[Иванов, 1980, Новокузнецк], [Иванов, 1971, Псков], [Петров, 1999, Москва], [Попов, 1980, Новокузнецк], [Степанов, 1980, Москва]}
Пример 2: реализация предыдущего примера с помощью метода.
string F(People p)
{
return p.Surname;
164
}
var Result = Peoples.OrderBy(F);
// Result = {[Антонов, 2001, Новокузнецк],
[Иванов, 1980, Новокузнецк], [Иванов, 1971, Псков], [Петров, 1999, Москва], [Попов, 1980, Новокузнецк], [Степанов, 1980, Москва]}
Пример 3: отсортировать людей в алфавитном порядке фамилий. При наличии людей с одинаковыми фамилиями, отсортировать их по году рождения.
var Result = Peoples.OrderBy(p => p.Surname)
.OrderBy(p => p.YearOfBirth);
// Result = {[Иванов, 1971, Псков], [Иванов, 1980, Новокузнецк], [Попов, 1980, Новокузнецк], [Степанов, 1980, Москва], [Петров, 1999, Москва], [Антонов, 2001, Новокузнецк]}
Приведенный выше пример не дал требуемого результата. Вместо двухкритериальной сортировки были выполнены две независимые сортировки последовательно. Для выполнения многокритериальной сортировки требуется использовать методы ThenBy(keySelector) (сортировка по возрастанию) или ThenByDescending(keySelector) (сортировка по убыванию) для второго и последующих критериев.
var Result = Peoples.OrderBy(p => p.Surname)
.ThenBy(p => p.YearOfBirth); // Result = {[Антонов, 2001, Новокузнецк],
[Иванов, 1971, Псков], [Иванов, 1980, Новокузнецк], [Петров, 1999, Москва], [Попов, 1980, Новокузнецк], [Степанов, 1980, Москва]}
9.3.4 Метод GroupBy
Метод GroupBy(keySelector) используется для группировки элемента последовательности по некоторому признаку. Для определения метода группировки используется keySelector – реализация делегата Func, входным параметром которого является элемент последовательности, а выходным – значение, по которому осуществляется группировка элементов.
Пример 1: сгруппировать данные о людях по городу их проживания и вывести в алфавитном порядке названий городов. В пределах каждого города выводить людей в алфавитном порядке фамилий. Вывод осуществлять в компонент
класса TextBox (реализация с использованием лямбда-выражения).
People[] Peoples = new People[6];
Peoples[0] = new People() { Surname = "Иванов", YearOfBirth = City = "Новокузнецк" };
Peoples[1] = new People() { Surname = "Петров", YearOfBirth = 1999, City = "Москва" };
165
Peoples[2] = new People() { Surname = "Иванов", YearOfBirth = 1971, City = "Псков" };
Peoples[3] = new People() { Surname = "Степанов", YearOfBirth = 1980, City = "Москва" };
Peoples[4] = new People() { Surname = "Антонов", YearOfBirth = 2001, City = "Новокузнецк" };
Peoples[5] = new People() { Surname = "Попов", YearOfBirth = 1980, City = "Новокузнецк" };
var Result = Peoples.OrderBy(p => p.Surname). GroupBy(p => p.City).OrderBy(p => p.Key);
Result_TB.Clear();
foreach (var group in Result)
{
Result_TB.AppendText(group.Key + "\n");
foreach (var p in group) |
|
Result_TB.AppendText(" |
" + p.Surname + "\n"); |
} |
|
Результат будет выведен в виде:
Москва
Петров
Степанов
Новокузнецк
Антонов
Иванов
Попов
Псков
Иванов
В данном примере сначала осуществляется сортировка в алфавитном порядке фамилий (чтобы в пределах группы была выполнена правильная сортировка), потом группировка по городу проживания, и затем – сортировка по ключу группировки (городу проживания), чтобы группы выводились в заданном порядке.
Пример 2: реализация предыдущего примера с помощью метода.
string F(People p)
{
return p.City;
}
var Result = Peoples.OrderBy(p => p.Surname).GroupBy(F)
.OrderBy(p => p.Key);
166