Новые фичи C#

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

Реклама
Tagged with: , , , , , , ,
Опубликовано в .Net, Development

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход /  Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход /  Изменить )

Connecting to %s

%d такие блоггеры, как: