Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Базовые технологии платформы .NET.docx
Скачиваний:
11
Добавлен:
18.08.2019
Размер:
423.24 Кб
Скачать

12. Операторы преобразования.

Назначение данных операторов – преобразования универсальных коллекций, реализующих IEnumerable<T>, в конкретные типы.

Оператор AsEnumerable() возвращает свой аргумент, приведённый к типу IEnumerable<T>. Этот оператор необходим в том случае, если тип аргумента source имеет методы, аналогичные имеющимся в LINQ to Objects.

IEnumerable<T> AsEnumerable<T>(this IEnumerable<T> source);

Операторы ToArray() и ToList() выполняют преобразование коллекции в массив или список.

T[] ToArray<T>(this IEnumerable<T> source);

List<T> ToList<T>(this IEnumerable<T> source);

Существует несколько версий оператора ToDictionary(), порождающего из коллекции словарь. Например, следующая версия использует отдельные функции для выделения из элемента коллекции ключа и значения ключа.

Dictionary<K, V> ToDictionary<T, K, V>(this IEnumerable<T> source,

Func<T, K> keySelector,

Func<T, V> valueSelector);

Оператор ToLookup() преобразовывает коллекцию в объект класса Lookup<K, V> из пространства имён System.Linq. Класс Lookup<K, V> представляет словарь, в котором ключу сопоставлен не единственный элемент, а набор элементов.

ILookup<K, V> ToLookup<T, K, V>(this IEnumerable<T> source,

Func<T, K> keySelector,

Func<T, V> valueSelector);

Оператор OfType<T>() итерируется по коллекции и генерирует список, содержащий только элементы заданного типа T.

IEnumerable<T> OfType<T>(this IEnumerable source);

Оператор Cast<T>() итерируется по слаботипизированной коллекции и пытается выполнить приведение каждого элемента к указанному типу. Если приведение выполнить не удаётся, генерируется исключение. Данный оператор полезен, если мы хотим применять LINQ для старых коллекций, таких, как ArrayList.

IEnumerable<T> Cast<T>(this IEnumerable source);

Из операторов преобразования отложенные вычисления выполняют операторы AsEnumerable<T>(), OfType<T>(), Cast<T>().

Язык C# версии 3.0 вводит новые ключевые слова и особые синтаксические расширения для записи некоторых операторов LINQ в виде выражений запросов. Составленное выражение запросов должно подчиняться следующим правилам (за строгим описанием правил следует обратиться к MSDN):

1. Выражение должно начинаться с конструкции from, которая указывает на обрабатываемую коллекцию.

2. Затем выражение может содержать ноль или более конструкции from, let или where. Конструкция let представляет переменную и присваивает ей значение. Конструкция where фильтрует элементы коллекции.

3. Затем выражение может включать ноль или более конструкций orderby, с полями сортировки и необязательным указанием на направление упорядочивания. Направление может быть ascending или descending.

4. Затем следует конструкция select или group.

5. Наконец, в оставшейся части выражения может следовать необязательная конструкция продолжения. Такой конструкцией является into.

Выражения запросов транслируются компилятором в вызовы соответствующих операторов LINQ. Приведём некоторые примеры эквивалентной записи запросов к коллекциям данных.

var r1 = gr.Where(s => s.Age > 20).Select(s => s.Marks);

// эквивалентный синтаксис

var r2 = from s in gr

where s.Age > 20

select s.Marks;

var r3 = gr.OrderByDescending(s => s.Age).ThenBy(s => s.Name);

// эквивалентный синтаксис

var r4 = from s in gr

orderby s.Age descending, s.Name

select s;

var r5 = gr.Select(student => new {student.Name, student.Age});

// эквивалентный синтаксис

var r6 = from student in gr select new {student.Name, student.Age};

Приведём несколько примеров использования технологии LINQ to Objects. В первом примере подсчитывается частота вхождения каждого слова в текст.

var text = "this is the text and this is the code for the text";

var words = text.Split(' ');

var result = words.GroupBy(word => word.ToUpper())

.Select(group => new {group.Key, Count = group.Count()})

.OrderBy(pair => pair.Count);

foreach (var pair in result)

Console.WriteLine("{0} - {1}", pair.Count, pair.Key);

Второй пример – метод расширения, демонстрирующий идею алгоритма быстрой сортировки (так как LINQ to Objects использует отложенные вычисления, метод выполняется медленно).

public static IEnumerable<T> QSort<T>(this IEnumerable<T> data)

where T : IComparable<T>

{

var tail = data.Skip(1);

if (tail.Any())

{

var elem = data.First();

var head = data.Take(1);

var left = tail.Where(x => x.CompareTo(elem) < 0).QSort();

var right = tail.Where(x => x.CompareTo(elem) >= 0).QSort();

return left.Concat(head).Concat(right);

}

return data;

}