C# 6 поставляется с Visual Studio 2015 Preview. Философия этой версии проста: улучшить простые повседневные сценарии кодирования, не добавляя много концептуальных новых вещей. Новые возможности должны сделать процесс коддинга легче, при этом не делая язык тяжелее.
Сейчас я проведу вас через каждую новую особенность языка. Мы начнем на уровне экспрессии и будем двигаться «наружу». Можно быть уверенным, что это тот набор, который будет в конечном итоге, но уже известно, что некоторые из них несколько изменятся.
nameof выражения — новая форма строки, для которой потребуется больше синтаксиса и она более ограничена. Неужели что-то не нравится? 🙂
На самом деле есть много причин для того, чтобы полюбить данный функционал. Часто необходимо задать строку с именем некоторых элементов: например, когда бросаем ArgumentNullException и необходимо передать имя “виновного” в ошибке; при вызове события PropertyChanged и т.д.
Использование обычных строковых значений для данных целей является простым функционалом, но может вызвать ошибки. Вы можете неправильно записать имя или после рефакторинга оставить его устаревшим.
(if x == null) throw new ArgumentNullException(nameof(x));
Вы можете задать более сложное выражение в nameof, но это только для того, чтобы сообщить компилятору, где искать:
WriteLine(nameof(person.Address.ZipCode)); // выведет "ZipCode"
String interpolation позволяет вам более легко формировать строки. String.Format и его двоюродные братья очень универсальны, но их использование является несколько неуклюжим и приводящим к ошибкам. Особенно прискорбным является использование пронумерованных заполнителей, таких как “{0}”, в строке формата, которые должны совпадать с отдельно указанными аргументами:
var s = String.Format("{0} is {1} year{{s}} old", p.Name, p.Age);
String interpolation позволяет поместить выражения прямо на их место:
var s = "\{p.Name} is \{p.Age} year{s} old";
Так же, как и со String.Format, есть возможность добавить дополнительные выравнивания и форматы:
var s = "\{p.Name,20} is \{p.Age:D3} year{s} old";
Содержание таких “вставок” могут быть различные, например, тернарное выражение:
var s = "\{p.Name} is \{p.Age} year\{(p.Age == 1 ? "" : "s")} old";
Обратите внимание, что условное выражение в скобках.
Примечание: здесь описывается синтаксис, который работает в VS Preview. Тем не менее, синтаксис скорее всего будет изменен и в более поздних версиях вы увидите интерполированные строки, написанные таким образом:
var s = $"{p.Name,20} is {p.Age:D3} year{{s}} old";
Null-conditional operators решает многие ситуации, когда нам приходилось проверять переменные null перед обращением к ним. Такие операции позволяют получить доступ к элементу только тогда, когда он не является нулевым, иначе обеспечивает нулевой результат:
int? length = customers?.Length; // null если customers null Customer first = customers?[0]; // null если customers null
Данный оператор очень удобно использовать вместе с со следующим оператором “??”:
int length = customers?.Length ?? 0; // 0 если customers null
Также можно смело прописывать функционал после данного оператора — если изначальное условие не будет выполняться — он прекратит работу и вернет null:
int? first = customers?[0].Orders.Count(); // если customers null, то результат будет null
По сути следующий пример — то же самое:
int? first = (customers != null) ? customers[0].Orders.Count() : null;
Также таким образом мы можем проверять на null дальнейшие обращения:
int? first = customers?[0].Orders?.Count();
Обратите внимание, что вызов (передача параметров в скобках) не может следовать сразу после оператора ‘?’ — т.к. это приведет к слишком многим синтаксических двусмысленностям:
if (predicate?(e) ?? false) { … } // Error!!
Тем не менее, вы можете запустить это сценарий с помощью метода Invoke:
if (predicate?.Invoke(e) ?? false) { … }
Это простой и потокобезопасный способ проверить на null, прежде чем вызвать событие.
Index initializers призвано расширить инициализацию объектов во вновь созданном объектом:
var numbers = new Dictionary<int, string> { [7] = "seven", [9] = "nine", [13] = "thirteen" };
Exception filters — способность CLR, которая уже давно реализована для Visual Basic и F #, но не было для C#. Выглядит это следующим образом:
try { … } catch (MyException e) if (myfilter(e)) { … }
Если выражение в скобках после «if» истинно, catch сработает.
Await в catch и в finally который был невозможен до сих пор. На самом деле это было существенным ограничением и люди приходилось использовать обходные пути (костыли). Но теперь Вы можете обойтись без них:
Resource res = null; try { res = await Resource.OpenAsync(…); // You could always do this. … } catch(ResourceException e) { await Resource.LogAsync(res, e); // Now you can do this … } finally { if (res != null) await res.CloseAsync(); // … and this. }
Auto-property initializers появилась в новой версии языка; подобна инициализации полей:
public class Customer { public string First { get; set; } = "Jane"; public string Last { get; set; } = "Doe"; }
Getter-only auto-properties позволяют опускать функционал сеттер в авто-свойствах:
public class Customer { public string First { get; } = "Jane"; public string Last { get; } = "Doe"; }
Поле по сути будет являться ReadOnly. Оно может быть инициализировано через инициализацию при определении (как в примере выше) или же оно может быть установлено в какое-либо значение в теле конструктора объявляющего типа, которое присваивается непосредственно к основной области:
public class Customer { public string Name { get; }; public Customer(string first, string last) { Name = first + " " + last; } }
Expression-bodied function members позволяют определять методы, свойства и другие виды функций-членов в виде выражений, а не блоков, так же, как с лямбда-выражениями.
Тело методы могут быть представлено выражением с использованием лямбда-выражения:
public Point Move(int dx, int dy) => new Point(x + dx, y + dy); public static Complex operator +(Complex a, Complex b) => a.Add(b); public static implicit operator string(Person p) => "\{p.First} \{p.Last}";
Эффект в точности такой же, как если бы у методов были блоковые тела.
public void Print() => Console.WriteLine(First + " " + Last);
Свойства и индексаторы могут иметь только get или get/set методы и у индексаторов могут быть только тела выражении:
public string Name => First + " " + Last; public Customer this[long id] => store.LookupCustomer(id);
Parameterless constructors in structs допускаются в данный момент:
struct Person { public string Name { get; } public int Age { get; } public Person(string name, int age) { Name = name; Age = age; } public Person() : this("Jane Doe", 37) { } }
Выражение “new Person()” будет выполнять заявленный конструктор вместо стандартного поведения предоставления значение по умолчанию. Необходимо подметить, что «default(Person)» будет по-прежнему возвращать значение по-умолчанию.
using static — новый вид using, которое позволяет импортировать статические члены типов непосредственно.
В Preview выглядит следующим образом:
using System.Console; using System.Math; class Program { static void Main() { WriteLine(Sqrt(3*3 + 4*4)); } }
Это очень удобно, если у вас есть набор функций, относящихся к определенному пространству имен, например, System.Math.
Ссылка на источник: New Features in C# 6
Добавить комментарий