Чтение онлайн

ЖАНРЫ

Язык программирования C#9 и платформа .NET5
Шрифт:

Синтаксис инициализации объектов и коллекций

В главе 5 объяснялась роль синтаксиса инициализации объектов, который позволяет создавать переменную типа класса или структуры и устанавливать любое количество ее открытых свойств за один прием. В результате получается компактный (и по-прежнему легко читаемый) синтаксис, который может использоваться для подготовки объектов к потреблению. Также вспомните из главы 10, что язык C# поддерживает похожий синтаксис инициализации коллекций объектов. Взгляните на следующий фрагмент кода, где синтаксис инициализации коллекций применяется для наполнения

List<T>
объектами
Rectangle
, каждый из которых состоит из пары объектов
Point
,
представляющих точку с координатами (х, у):

List<Rectangle> myListOfRects = new List<Rectangle>

{

new Rectangle {TopLeft = new Point { X = 10, Y = 10 },

BottomRight = new Point { X = 200, Y = 200}},

new Rectangle {TopLeft = new Point { X = 2, Y = 2 },

BottomRight = new Point { X = 100, Y = 100}},

new Rectangle {TopLeft = new Point { X = 5, Y = 5 },

BottomRight = new Point { X = 90, Y = 75}}

};

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

Лямбда-выражения

Лямбда-операция C# (

=>
) подробно рассматривалась в главе 12. Вспомните, что данная операция позволяет строить лямбда-выражение, которое может применяться в любой момент при вызове метода, требующего строго типизированный делегат в качестве аргумента. Лямбда-выражения значительно упрощают работу с делегатами, т.к. сокращают объем кода, который должен быть написан вручную. Лямбда-выражения могут быть представлены следующим образом:

АргументыДляОбработки =>

{

ОбрабатывающиеОператоры

}

В главе 12 было показано, как взаимодействовать с методом

FindAll
обобщенного класса
List<T>
с использованием трех разных подходов. После работы с низкоуровневым делегатом
Predicate<T>
и анонимным методом C# мы пришли к приведенной ниже (исключительно компактной) версии, в которой использовалось лямбда-выражение:

static void LambdaExpressionSyntax

{

// Создать список целочисленных значений.

List<int> list = new List<int>;

list.AddRange(new int[] { 20, 1, 4, 8, 9, 44 });

// Теперь использовать лямбда-выражение С#.

List<int> evenNumbers = list.FindAll(i => (i % 2) == 0);

// Вывести четные числа

Console.WriteLine("Here are your even numbers:");

foreach (int evenNumber in evenNumbers)

{

Console.Write("{0}\t", evenNumber);

}

Console.WriteLine;

}

Лямбда-выражения будут удобны при

работе с объектной моделью, лежащей в основе LINQ. Как вы вскоре выясните, операции запросов LINQ в C# — просто сокращенная запись для вызова методов класса по имени
System.Linq.Enumerable
. Эти методы обычно всегда требуют передачи в качестве параметров делегатов (в частности, делегата
Funс<>
), которые применяются для обработки данных с целью выдачи корректного результирующего набора. За счет использования лямбда-выражений можно упростить код и позволить компилятору вывести нужный делегат.

Расширяющие методы

Расширяющие методы C# позволяют оснащать существующие классы новой функциональностью без необходимости в создании подклассов. Кроме того, расширяющие методы дают возможность добавлять новую функциональность к запечатанным классам и структурам, которые в принципе не допускают построения подклассов. Вспомните из главы 11, что когда создается расширяющий метод, первый его параметр снабжается ключевым словом

this
и помечает расширяемый тип. Также вспомните, что расширяющие методы должны всегда определяться внутри статического класса, а потому объявляться с применением ключевого слова
static
. Вот пример:

namespace MyExtensions

{

static class ObjectExtensions

{

// Определить расширяющий метод для System.Object.

public static void DisplayDefiningAssembly(

this object obj)

{

Console.WriteLine("{0} lives here:\n\t->{1}\n", obj.GetType.Name,

Assembly.GetAssembly(obj.GetType));

}

}

}

Чтобы использовать такое расширение, приложение должно импортировать пространство имен, определяющее расширение (и возможно добавить ссылку на внешнюю сборку). Затем можно приступать к написанию кода:

// Поскольку все типы расширяют System.Object, все

// классы и структуры могут использовать это расширение.

int myInt = 12345678;

myInt.DisplayDefiningAssembly;

System.Data.DataSet d = new System.Data.DataSet;

d.DisplayDefiningAssembly;

При работе c LINQ вам редко (если вообще когда-либо) потребуется вручную строить собственные расширяющие методы. Тем не менее, создавая выражения запросов LINQ, вы на самом деле будете применять многочисленные расширяющие методы, уже определенные разработчиками из Microsoft. Фактически каждая операция запроса LINQ в C# представляет собой сокращенную запись для ручного вызова лежащего в основе расширяющего метода, который обычно определен в служебном классе

System.Linq.Enumerable
.

Анонимные типы

Последним средством языка С#, описание которого здесь кратко повторяется, являются анонимные типы, рассмотренные в главе 11. Данное средство может использоваться для быстрого моделирования "формы" данных, разрешая компилятору генерировать на этапе компиляции новое определение класса, которое основано на предоставленном наборе пар "имя-значение". Вспомните, что результирующий тип составляется с применением семантики на основе значений, а каждый виртуальный метод

System.Object
будет соответствующим образом переопределен. Чтобы определить анонимный тип, понадобится объявить неявно типизированную переменную и указать форму данных с использованием синтаксиса инициализации объектов:

Поделиться с друзьями: