Секреты LINQ. Автогенерируемые свойства. Инициализаторы объектов и коллекций, страница 24

¨  Для прохода вдоль последовательности g, имеющей тип IGrouping<int,int>, также необходимо привести ее к типу Array. Это также делает extension-метод ToArray.

¨  Первая лямбда-операция (читай — код делегата) имеет более сложный вид, чем вторая. Блок кода, реализующий ее, содержит вложенную лямбда-операцию y => Console.Write(y + ", ").

Лямбда-выражения могут быть составными. Следующий пример показывает, что λ-выражение с двумя параметрами эквивалентно последовательности двух λ-выражений с одним параметром.

Console.Write("\nTest (x, y) => x + y: ");

Func<int, int, int> lambda = (x, y) => x + y;

Console.WriteLine (lambda(3, 4));

Func<int, Func<int, int>> curry = x => y => x + y;

Console.Write ("Test x => y => x + y: ");

Console.WriteLine (curry(3)(4));

Интерфейс IQueryable <T>

Мы убедились, что источником данных для LINQ-запроса может быть любая коллекция, реализующая интерфейс IEnumerable<T>. Но им также может быть и любой объект, реализующий интерфейс IQueryable<T>.

public interface IQueryable<out T> : IEnumerable<T>, IQueryable, IEnumerable

Параметр T является ковариантным. Это означает, что вместо типа T вы можете подать и любой из типов, производных от T. Типы, реализующие IQueryable<T>, не являются коллекциями. Они представляют собой описания запросов, которые генерируются динамически и поддерживают полиморфизм и оптимизацию. Такие типы, совместно с деревьями выражений (expression trees) допускают компиляцию запросов с целью повышения производительности, и могут служить входными данными для образования других LINQ-запросов.

Интерфейс IQueryable (так же как и IEnumerable) задает сигнатуру только одного метода.

IEnumerator GetEnumerator()

Интерфейс IQueryProvider определяет методы, необходимые для создания и исполнения запросов, определенных IQueryable-типом. Интерфейс IQueryProvider задает сигнатуру двух методов:

IQueryable CreateQuery(Expression expression);

object Execute <TResult>(Expression)

Цепочка действий, которая выполняется при вызове метода Execute <TResult>(Expression) зависит от провайдера данных. Одним из вариантов реализации запроса может быть трансляция дерева выражения в текст запроса, удовлетворяющего синтаксису конкретного языка запросов. Конкретный язык запросов определяется провайдером данных.

COM Interop

Следующий пример показывает, как используются новые возможности C# 4.0 для управления объектами COM Interop. В частности для создания документов Microsoft Office (Excel и Word). Новые возможности (именованные параметры и индексируемые свойства) сильно упрощают общение с Office API.

using System;

using System.Collections.Generic;

using System.Drawing;

using Excel = Microsoft.Office.Interop.Excel;

using Word = Microsoft.Office.Interop.Word;

public class Account

{

public int ID { get; set; }

public double Balance { get; set; }

}

public class Program

{

static void Main()

{

var checkAccounts = new List<Account>

{

new Account { ID = 345, Balance = 541.27 },

new Account { ID = 123, Balance = -127.44 }

};

Action<Account, Excel.Range> display = (account, cell) =>

{

cell.Value = account.ID;

cell.Offset[0, 1].Value = account.Balance;

if (account.Balance < 0)

{

cell.Interior.Color = ColorTranslator.ToOle(Color.FromArgb(255,255,200));

cell.Offset[0, 1].Interior.Color = ColorTranslator.ToOle(Color.LightSkyBlue);

}

};

DisplayInExcel(checkAccounts, display);

var word = new Word.Application();

word.Visible = true;

word.Documents.Add();

word.Selection.PasteSpecial(Link: true, DisplayAsIcon: false);

}

public static void DisplayInExcel(IEnumerable<Account> accounts, Action<Account, Excel.Range> display)

{

var xl = new Excel.Application();

xl.Workbooks.Add();

xl.Visible = true;

xl.Cells[1, 1] = "ID";

xl.Cells[1, 2] = " Balance";

xl.Cells[2, 1].Select();

foreach (var ac in accounts)

{

display(ac, xl.ActiveCell);