Си Шарп 3.0
Язык программирования C# версии 3.0 был выпущен 19 ноября 2007 года как часть .NET Framework 3.5 . Он включает в себя новые функции, вдохновленные функциональными языками программирования, такими как Haskell и ML , и во многом обусловлен введением шаблона Language Integrated Query (LINQ) в среду Common Language Runtime. [1] В настоящее время он не стандартизирован ни одной организацией по стандартизации .
Возможности С# 3.0
[ редактировать ]LINQ (интегрированный в язык запрос)
[ редактировать ]LINQ — это новый расширяемый язык запросов общего назначения, предназначенный специально для Microsoft, для многих типов источников данных, включая коллекции простых объектов, XML-документы, базы данных и т. д., который тесно интегрирован с другими средствами языка C#. Синтаксис отличается от SQL , но заимствован из него . Пример:
int[] array = { 1, 5, 2, 10, 7 };
// Select squares of all odd numbers in the array sorted in descending order
IEnumerable<int> query = from x in array
where x % 2 == 1
orderby x descending
select x * x;
// Result: 49, 25, 1
Для реализации LINQ во многие коллекции был добавлен большой набор новых методов через System.Linq.Enumerable
сорт. Выражения LINQ преобразуются для использования этих функций перед компиляцией. В качестве альтернативы, которая иногда является более мощной или прямой, к этим функциям можно получить прямой доступ. [2] При этом шире используются лямбда-функции, которые обсуждаются ниже. Следующее функционально идентично приведенному выше примеру.
IEnumerable<int> query = array.Where(x => x % 2 == 1)
.OrderByDescending(x => x)
.Select(x => x * x);
// Result: 49, 25, 1 using 'array' as defined in previous example
Инициализаторы объектов
[ редактировать ]Customer c = new Customer();
c.Name = "John";
можно написать
Customer c = new Customer { Name = "John" };
Инициализаторы коллекций
[ редактировать ]MyList list = new MyList();
list.Add(1);
list.Add(2);
можно записать как
MyList list = new MyList { 1, 2 };
предполагая, что MyList
реализует System.Collections.IEnumerable
и имеет общественность Add
метод. [3]
Вывод типа локальной переменной
[ редактировать ]локальной переменной Вывод типа :
var x = new Dictionary<string, List<float>>();
взаимозаменяем с
Dictionary<string, List<float>> x = new Dictionary<string, List<float>>();
Эта возможность является не просто удобным синтаксическим сахаром для более коротких объявлений локальных переменных, но она также необходима для объявления переменных анонимных типов. Однако контекстное ключевое слово «var» может появляться только в объявлении локальной переменной.
Анонимные типы
[ редактировать ]Анонимные типы предоставляют удобный способ инкапсулировать набор свойств, доступных только для чтения, в один объект без необходимости предварительного явного определения типа. Имя типа генерируется компилятором и недоступно на уровне исходного кода. Тип свойств определяется компилятором.
var x = new { FirstName = "John", LastName = "Doe" };
Анонимные типы — это ссылочные типы , производные непосредственно от объекта. Компилятор дает им имя, хотя ваше приложение не может получить к нему доступ. С точки зрения среды CLR анонимный тип ничем не отличается от любого другого ссылочного типа, за исключением того, что его нельзя привести к какому-либо типу, кроме объекта.
Если два или более анонимных типа имеют одинаковое количество и тип свойств в одном и том же порядке, компилятор рассматривает их как один и тот же тип, и они используют одну и ту же информацию о типе, созданную компилятором. [4]
Лямбда-выражения
[ редактировать ]Лямбда -выражения предоставляют краткий способ записи значений первоклассных анонимных функций. Сравните следующий фрагмент C# 2.0:
listOfFoo.Where(delegate(Foo x) { return x.Size > 10; });
с этим эквивалентом С# 3.0:
listOfFoo.Where(x => x.Size > 10);
В приведенных выше примерах лямбда-выражения представляют собой просто сокращенный синтаксис для анонимных делегатов с выводом типа для параметров и типа возвращаемого значения. Однако, в зависимости от контекста, в котором они используются, компилятор C# также может преобразовывать лямбды в AST , которые затем можно обрабатывать во время выполнения. В приведенном выше примере, если listOfFoo
не является простой коллекцией в памяти, а является оболочкой таблицы базы данных, он может использовать этот метод для перевода тела лямбды в эквивалентное выражение SQL для оптимизации выполнения. В любом случае, само лямбда-выражение выглядит в коде точно так же, поэтому способ его использования во время выполнения прозрачен для клиента.
Деревья выражений
[ редактировать ]Выражения, такие как x <= y
, a = b + c
или даже лямбда-функции и другие сложные формы могут создаваться динамически с использованием деревьев выражений . Большая часть функциональности обеспечивается статическими методами класса. System.Linq.Expressions.Expression
. В этом пространстве имен также есть различные новые классы, которые представляют выражения и частичные выражения, созданные этими методами, как программные объекты. К ним относятся BinaryExpression
, который мог бы представлять x <= y
; LambdaExpression
и многие другие. В сочетании с аспектами API отражения это может быть очень мощным инструментом, хотя его немного сложно писать и отлаживать. [5] [6]
Автоматические свойства
[ редактировать ]Компилятор генерирует частную переменную экземпляра и соответствующий код доступа и мутатора, например:
public string Name { get; private set; }
Методы расширения
[ редактировать ]Разработчики могут использовать методы расширения для добавления новых методов в публичный контракт существующего типа CLR без необходимости создания его подкласса или перекомпиляции исходного типа. На самом деле методы расширения — это форма синтаксического сахара, создающая иллюзию добавления новых методов к существующему классу за пределами его определения. Иллюзия достигается за счет определения статического метода, который можно вызывать, как если бы это был метод экземпляра, где получатель вызова (т. е. экземпляр) привязан к первому параметру метода, украшенному ключевым словом this
.
Требования к методу расширения следующие:
- Метод расширения должен быть определен в статическом классе.
- Метод расширения должен быть определен как статический метод.
- Первый параметр метода расширения должен иметь следующую форму, где тип — это имя расширяемого типа:
this type parameterName
- Метод расширения может дополнительно определять другие параметры, соответствующие
this
параметр.
Этот пример класса демонстрирует определение и использование Left
метод расширения для строк:
public static class StringExtensions
{
public static string Left(this string s, int n)
{
return s.Substring(0, n);
}
}
string s = "foo bar";
s.Left(3); // same as StringExtensions.Left(s, 3), which returns "foo";
Частичные методы
[ редактировать ]Частичные методы позволяют генераторам кода генерировать объявления методов как точки расширения, которые включаются в компиляцию только в том случае, если кто-то действительно реализует их в другой части частичного класса. [7]
Ссылки
[ редактировать ]- ^ Андерсон, Тим (14 ноября 2006 г.). «C# опережает Java – ведущий архитектор рисует радужную картину C#» . Рег Разработчик . Регистр . Проверено 20 января 2007 г.
- ^ Вальтер, Стивен (2008). Выпуск ASP.NET 3.5 . Индиана, США: SAMS. стр. 916–917 . ISBN 978-0-672-33011-7 .
Я обнаружил, что использую синтаксис метода чаще, чем синтаксис запроса, поскольку синтаксис запроса является подмножеством синтаксиса метода.
- ^ Торгерсен, Мадс (10 октября 2006 г.). «Что такое коллекция?» . Мягкие размышления доктора Т. Проверено 18 июня 2009 г.
- ^ «Анонимные типы» . Руководство по программированию на C# . Майкрософт . Июль 2008 года . Проверено 18 июня 2009 г.
- ^ Вальтер, Стивен (2008). Выпуск ASP.NET 3.5 . Индиана, США: SAMS . стр. 950–952 . ISBN 978-0-672-33011-7 .
- ^ «Деревья выражений» . Руководство разработчика .NET Framework . Майкрософт . Проверено 26 апреля 2009 г.
- ^ «Частичные классы и методы» . Руководство по программированию на C# . Майкрософт . Проверено 28 апреля 2009 г.