Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции по ООП (язык C#).pdf
Скачиваний:
190
Добавлен:
16.05.2015
Размер:
1.54 Mб
Скачать

Чернов Э. А.

- 110 -

Лекции по языку C# v 2.3

default(Т). Для ссылочных и допускающих null типов значением по умолчанию является null.

Второй прототип FirstOrDefault

Второй прототип операции FirstOrDefault позволяет передать predicate, определяющий, какой элемент следует возвратить.

public static Т FirstOrDefault<T>( this IEnumerable<T> source, Func<T, bool> predicate);

Код ниже, содержит пример использования первого прототипа FirstOrDefault, где элемент не найден. Для этого понадобилась пустая последовательность, которая была создана с помощью Таке(0):

string aut = cars.Last();// Выборка самого последнего элемента

Console.WriteLine("\nВызов первого прототипа: " + aut); // Выборка последнего элемента на букву "A"

string auto1 = cars.Last(p => p.StartsWith("A")); Console.WriteLine("\nВызов второго прототипа: " + auto1);

Группировка

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

Принципиально важно: для группировки должно существовать название для группы (ключ) и значения.

Для выполнения группировки сначала выбирается критерий для формирования группы (называемый ключом (<K>)), а затем формируются объекты нового класса (<T>). После выбора критерия группировки определяют, какие элементы отбирать в группу. Помощь в реализации группы оказывает интерфейс IGrouping<K, T>.

Выборку объектов для группировки реализуют с помощью ключевых слов group, by и into. Эти операции позволяют выбрать объекты для группировки, указать принцип формирования группы, и указать псевдоним, используемый для ссылки на отдельные группы. Ниже приведен пример группировки объектов на примере списка студентов в разных группах и пометок об успеваемости.

class Program

{

public class Trails

{

public string name { get; set; }// фамилия

Чернов Э. А.

- 111 -

Лекции по языку C# v 2.3

public string secname { get; set; }// имя public string grp { get; set; } // Группа

public int sc1 { get; set; }// Физика 1 - отставание, 0 сдано public int sc2 { get; set; }// Электроника

public Trails() { } // Конструктор пустой

// Конструктор с параметрами

public Trails(string s, string sn, string gr, int f, int e)

{

name = s; secname = sn; grp = gr;

sc1 = f; sc2 = e;

}

}

static void Main(string[] args)

{

StreamReader file = new StreamReader("C:\\Temp\\studt.txt", Encoding.Default);

string s;

int sk1, sk2; string[ ] str;

Trails blk = new Trails();// List<Trails> lst = new List<Trails>(); while ((s = file.ReadLine()) != null)

{

str = s.Split(' ');

sk1 = int.Parse(str[3]); sk2 = int.Parse(str[4]);

lst.Add(new Trails(str[0], str[1], str[2], sk1, sk2));

}

Console.WriteLine("Начальный список \n");

Console.WriteLine(" Фамилия

Имя Группа"+

 

 

" Физика Электроника \n");

foreach (Trails bl in lst)

// Вывод начального списка

Console.WriteLine("{0,-8}\t{1,-4}\t{2}\t{3,4}\t{4,6}",

 

bl.name, bl.secname, bl.grp, bl.sc1, bl.sc2);

Console.WriteLine("\nОтстают по физике");

var std_by_Group1 =

 

// Имя запроса

from cust in lst orderby cust.grp

// Сортировка по группам

where cust.sc1 == 1

 

// Условие отбора

group cust by cust.grp;

 

// Группировка по группам

foreach (var std_names in std_by_Group1 )

{

Console.WriteLine(std_names.Key); foreach (var std in std_names)

{

Console.WriteLine("{0,10}\t {1}", std.name, std.secname);

}

}

Чернов Э. А.

- 112 -

Лекции по языку C# v 2.3

Console.WriteLine("\nОтстают по электронике"); var Grp2= from cust in lst

where cust.sc2 == 1 // Условие отбора group cust by cust.grp;

foreach (var std_names in Grp2)

{

Console.WriteLine(std_names.Key); foreach (var std in std_names)

{

Console.WriteLine("{0,10}\t {1}", std.name, std.secname);

}

}

Console.ReadKey();

}

}

Результат выполнения программы имеет вид:

Делегаты

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

Сделегатами связаны два объявления:

Объявление собственно делегата. Делегат является классом, поэтому объявление делегата - это создание объекта типа делегата. Конструктор при этом объяв-

Чернов Э. А.

- 113 -

Лекции по языку C# v 2.3

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

Объявление переменной типа объявленного делегата. При этом объявлении также вызывается конструктор, но он содержит единственный параметр – имя метода, передаваемого делегату. Существует так называемое «групповое» преобразование, при котором вместо объявления переменной типа делегата просто выполняется присваивание. Фактически это упрощенное объявление переменной типа делегата. Возможно, именно эта упрощенная форма приводит к нечетким формулировкам при объявлении делегатов.

С методами связано понятие «сигнатуры». Сигнатура это имя метода и список параметров с точки зрения типов (имена параметров не учитываются). При объявлении объекта типа делегата указывается также тип возвращаемого значения. Это отличает сигнатуру метода от сигнатуры делегата.

При объявлении делегата применяется ключевое слово delegate. Общая форма объявления объекта класса делегата имеет вид:

delegate тип_возврата имя_делегата (список_параметров);

где

тип_возврата указывает на тип значения для возврата методами, вызываемых делегатом.

список параметров - параметры, передаваемые методам, которые будут вызываться делегатом.

Ниже приведен пример объявления объекта типа делегата:

В качестве параметров методов можно использовать имена подпрограмм, то есть ссылаться на методы. Это обеспечивает возможность применения функций обратного вызова. Например, алгоритму сортировки можно передать ссылку на метод сравнения двух значений. Изменяя алгоритм сравнения в подпрограмме, можно изменять порядок сортировки.

Ниже приведен пример объявления делегата и его применения. Делегат объявляется два раза: сначала объявляется переменная типа делегата, а затем объект типа этого делегата???? Объявленный делегат принимает методы с возвращаемым значением типа double, и единственным параметром является одномерный массив чисел того же типа. Делегат объявлен перед классом, в котором реализованы два статических метода (вычисление суммы и произведения элементов массива) и основная программа.

Обратите внимание:

1. Сигнатура делегата

Чернов Э. А.

- 114 -

Лекции по языку C# v 2.3

2.Делегат объявлен один раз с именем ap. При объявлении в него был передан метод (Calc_Sum), а параметр (массив) передается уже в имя (ap) делегата ArProc (это похоже на вызов конструктора с параметрами).

3.Для передачи делегату другого метода используется тот же делегат, но справа от знака равенства он как бы создается заново, и ему передается имя другого метода.

class Program

{

delegate double ArProc(double [ ] ar); class DelegateTest

{

//Подсчитать сумму элементов массива static double Calc_Sum (double [ ] a)

{

double sum = 0;

Console.WriteLine("Подсчитать сумму элементов массива"); foreach (double e in a)

sum += e; return sum;

}

//Подсчитать произведение элементов массива

static double Calc_Prod (double[ ] a)

{

double pr = 1;

Console.WriteLine("Подсчитать произведение элементов массива"); foreach (double e in a)

pr *= e; return pr;

}

static void Main()

{

double [ ] m = {1.5, 2.5, 3};// Объявление и инициализация массива

//Объявление переменной типа делегата

ArProc ap = new ArProc (Calc_Sum);

//Вызвать с помощью делегата метод для суммирования.

//Переменная res принимает возврат от метода Calc_Sum double res = ap(m); // ap уже объявлено, передать параметры

Console.WriteLine ("Вычисленная сумма = {0:F2} ", res);

//Передать делегату другой метод

ap = new ArProc (Calc_Prod); res = ap(m);

Console.WriteLine ("Вычисленное произведение = {0:F2} ", res); Console.ReadKey();

}

}

}

Ниже приведен результат выполнения программы.