WPF 4.6 и дальнейшие планы

На недавно прошедшей онлайн конференции dotNetConf организованной Microsoft, рассказывалось множество интересных вещей. И коль скоро было большое количество обсуждений по поводу WPF, что он живее всех живых, то хочется сделать краткий обзор доклада программных менеджеров WPF, что нового нас ждет в релизе, что уже можно посмотреть и к чему все идет. Действительно все так плохо и будет ли аналог нового движка для WPF, как например Razor для ASP.NET.

12 ноября 2014 года блог WPF ожил (сейчас активен тоже) и был представлен генеральный план развития фреймворка.


Здесь и далее, скриншоты с видео, так что качество не очень, но разглядеть все можно.

В начале выступления, ведущие Уни Равиндранатан (Unni Ravindranathan) и Харикришна Менон (Harikrishna Menon) обмолвились, что есть вещи, которые еще находятся в разработке, и они не имеют права о них рассказывать, NDA и все такое. Но то что они могут показать, внушает оптимизм и видно, что работа идет. Забегая вперед, скажу, что прежде всего разработчики подумали о быстродействии, например, как сократить визуальное дерево для конкретной целевой платформы.

Подробнее

Обзор новых элементов C# 6.0

В сети находится огромное количество информации по этой теме и все достаточно разрозненно. Хотелось прежде всего для себя систематизировать и обозначить новые возможности языка. Некоторые вещи являются синтаксическим сахаром, некоторые являются действительно новыми фичами. Хотя в свете возможностей предоставляемых Roslyn, понятие о «сахаре» и новых фичах несколько размывается. Ведь можно модифицировать язык и создавать свои диалекты. Так что возможно скоро большие команды будут использовать свои варианты языка. Или нет. Но это отдельная большая тема (вспоминается просто Jetbrains с их Resharper). Доступность описываемых фич описана на странице https://roslyn.codeplex.com/wikipage?title=Language%20Feature%20Status. Большая часть всех фич уже доступна и вызывает положительные эмоции. Хотя, честно сказать, не всё из того, что помечено как «должно работать» работает. Например, индексированные члены в словаре что-то не завелись, хотя остальное все работало как надо.

Активизация экспериментального компилятора

Для того, чтобы описываемые штуки завелись, необходимо использовать VS2014 cRoslynSDK, или же VS2013 с SDK, RoslynSDK. После того как все компоненты были установлены, можно создать новый проект, открыть файл проекта (.CSPROJ) в текстовом редакторе и добавить в конфигурацию сборки строку:

<LangVersion>experimental</LangVersion>

Обратите внимание, что именно с маленькой буквы надо писать «experimental», иначе не работает. Конечно, это будет поправлено ближе к релизу. После таких нехитрых приготовлений можно начинать эксперименты.

Краткий список нововведений

  • Exists: Already shipped in previous release
  • Done: Implemented for this release
  • Planned: Intended for this release
  • Maybe: Possibly intended for this release
  • Withdrawn: Probably not in this release
  • No: Not intended for this release

 

Feature Example C#
Primary constructors class Point(int x, int y) { … } Done
Auto-property initializers public int X { get; set; } = x; Done
Getter-only auto-properties public int Y { get; } = y; Done
Using static members using System.Console; … Write(4); Done
Dictionary initializer new JObject { [«x»] = 3, [«y»] = 7 } Done
Indexed member initializer new JObject { $x = 3, $y = 7 } Withdrawn
Indexed member access
  1. $name = c.$first + » » + c.$last;
Withdrawn
Declaration expressions int.TryParse(s, out var x); Done
Await in catch/finally try … catch { await … } finally { await … } Done
Exception filters catch(E e) if (e.Count > 5) { … } Done
Typecase Select Case o : Case s As String : … No
Guarded cases Select Case i : Case Is > 0 When i Mod 2 = 0 No
Partial interfaces Partial Interface I1 Exists
Binary literals 0b00000100 Planned
Digit separators 0xEF_FF_00_A0 Planned
Expression-bodied members public double Dist => Sqrt(X * X + Y * Y); Planned
Event initializers new Customer { Notify += MyHandler }; Planned
Null propagation customer?.Orders?[5]?.$price Done
Semicolon operator (var x = Foo(); Write(x); x * x) Maybe
Private protected private protected string GetId() { … } Withdrawn
Params IEnumerable int Avg(params IEnumerable<int> numbers) { … } Planned
Constructor Inference new Tuple(3, «three», true); Maybe
String interpolation «\{p.First} \{p.Last} is \{p.Age} years old.» Maybe
TryCast for nullable var x = TryCast(u, Integer?) Exists
Implicit implementation Class C : Implicitly Implements I Exists
NameOf operator string s = nameof(Console.Write); Planned

Подробнее

Async\Await методы и PostSharp

Сложность 300-400

Описание проблемы

Уже много чего написал насчет PostSharp, конкретных решений, кастом компонентов, общие принципы работы. Однако с выходом .Net 4.5 появилась новая фича со специальными словами async\await которые позволяют более просто и компактно описывать асинхронное поведение методов. Новый функционал хорош, но добавляет головной боли при использовании PostSharp, с методами помеченными async, использование классических аспектов не пройдет. Методы с маркером async разворачиваются в машину состояний, что не очень хорошо с точки зрения применения аспектов. Т.е. возьмем стандартную реализацию аспекта трассировщика с помощью  PostSharp:

И применим его к тестовому примеру с вызовом синхронных и асинхронных методов с исключениями и без:

Результат выполнения программы представлен ниже, и для большей наглядности я разукрасил выводы для каждого метода.

Подробнее

Async/Await для .Net 4.0 Video

Сложность 200-400

Буквально на днях в блоге разработчиков Base Class Library промелькнуло известие о том, что теперь можно использовать async/await и для кода написанного на .Net Framework 4. А это значит можно использовать удобный подход для асинхронной работы, даже если пользователи вашей программы до сих пор сидят на «старой, доброй XP» по тем или иным причинам. Естественно такая новость не могла пройти мимо меня, чтобы я не попробовал как оно на самом деле в использовании. Забегая вперед, и что вполне ожидаемо, работает все точно так же как и в 4.5 за исключением некоторых нюансов в процессе разработки.

Процесс работы с новыми возможностями показан на видео подкатом.

 

Hard’n’Heavy!

Async/Await для .Net 4.0

Сложность 200-400

Буквально на днях в блоге разработчиков Base Class Library промелькнуло известие о том, что теперь можно использовать async/await и для кода написанного на .Net Framework 4. А это значит можно использовать удобный подход для асинхронной работы, даже если пользователи вашей программы до сих пор сидят на «старой, доброй XP» по тем или иным причинам. Естественно такая новость не могла пройти мимо меня, чтобы я не попробовал как оно на самом деле в использовании. Забегая вперед, и что вполне ожидаемо, работает все точно так же как и в 4.5 за исключением некоторых нюансов в процессе разработки. Но обо всем по порядку.

Команда разработчиков анонсировала пакет дополнений, который позволяет использовать await в Visual Studio 2012 (в предыдущих версиях работать не будет). Выпущенный пакет может быть применен к следующим платформам (указанной версии или выше):

  • .NET Framework 4.0 (with KB2468871)
  • Silverlight 4
  • Windows Phone 7.5
  • И портируемые библиотеки опирающиеся на указанные платформы.

Т.е. это не встроенная фича .net 4.5?

И да и нет. Очень заманчиво думать, что новые ключевые слова await/async в C# являются чистым новым функционалом языка. В некоторой степени это так: компилятору необходимо проделать достаточно много сложной работы с вашим кодом, чтобы он мог ожидать операции.

Принимая вышесказанное во внимание, разработчики ожидают возможность использования await как только они переходят на новую студию – независимо от платформы языка. Если вы задумывались о том, как реализовано большинство фич языка, то вы можете догадаться, что многие вещи не просто данность и особенность языка. Множество конструкций языка опираются на вполне конкретные API, к примеру, методы расширения опираются на ExtensionAttribute, а foreach зависит от интерфейса IEnumerable. В случае с await потребуется давно любимый класс Task и некоторая хитрая обвязка, которая делает возможным использование await.

Подробнее

MS SQL 2011 (Denali) – With Result Set

Модификация возвращаемого набора данных (NEW)

В оригинальном звучании и в жизни эта возможность звучит как With Result Set. Эта штука позволяет менять имена и типы данных в возвращаемом хранимой процедурой наборе данных.

Перед тем, как мы углубимся в детали использования данной возможности, рассмотрим, как предыдущие версии SQL серверов обходились с данными, которые возвращает хранимая процедура. Какие возможности они предоставляли для работы с результатом.

Для демонстрации работы будем использовать в качестве примера таблицу tbl_Test состоящую из 3 колонок.

Подробнее

MS SQL 2011 (Denali) – Sequence

Sequence (NEW) — последовательность

Возможность которой не удивишь нынче пользователей Oracle, DB2, PostgreSQL и множества других реляционных баз данных, наконец-то появилась и в SQL Server. На арене Sequence!

Sequence – генерирует последовательность чисел так же как и identity. Однако основным плюсом sequence является то, что последовательность не зависит от какой-либо конкретной таблицы и является объектом базы данных.

Рассмотрим пример скрипта написанного на SQL Server 2008. Создание простой таблицы с двумя колонками, одна из которых будет авто инкрементальной.

Похожим образом создадим еще одну таблицу.

Как можно заметить из примеров, мы записали значения в таблицу при этом значение инкрементального поля автоматически и независимо от нас заполнилось. Мы не можем повторно использовать значение этого поля в другой таблице. Давайте посмотрим какой выход дает Sequence из этой ситуации.

Общий синтаксис для команды выглядит так:

Создадим последовательность чисел:

После выполнения указанного скрипта, в браузере объектов базы, в узле Sequences можно найти наш объект.

После того как объект создан, можно его использовать в создании и заполнении таблиц как показано ниже:

Если создать вторую таблицу в таком же духе, то можно снова использовать GenerateNumberSequence и получать сквозную нумерацию объектов.

Последовательность (Sequence) которую мы создали, можно посмотреть в системном каталоге sys.sequences.

Это не вся доступная информация по sequence, просто эти колонки нам понадобятся далее. Чтобы получить всю информацию замените имена колонок на звездочку. =) Про Is_Exhausted будет упомянуто позднее.

Sequence может быть следующих типов:

  • Int
  • Smallint
  • Tinyint
  • Bigint
  • Decimal
  • Numeric

Не обязательно начинать последовательность с единицы. Можно начинать с любого числа в пределах возможных значений объявленного типа. Например, для целочисленных значений это может быть от -2147483648 до 2147483647.

Проверим на практике, что скажет SQL Server при задании начального числа вне допустимого диапазона. Начнем с левой границы.

An invalid value was specified for argument ‘START WITH’ for the given data type.

Что и ожидалось. Теперь нарушим правую границу.

 

Сервер сообщит нам об ошибке так:

The sequence object ‘GenerateNumberSequence’ cache size is greater than the number of available values; the cache size has been automatically set to accommodate the remaining sequence values.

И если мы обратим внимание на колонку Is_Exhausted в каталоге sys.sequences, то увидим, что значение стало равно 1. Что говорит нам о невозможности дальнейшего использования данной последовательности.

При попытке создать таблицу с использованием такой последовательности, сервер выдаст ошибку:

The sequence object ‘GenerateNumberSequence’ has reached its minimum or maximum value. Restart the sequence object to allow new values to be generated.

Это можно трактовать как просьбу движка рестартовать указанную последовательность. Для этого необходимо воспользоваться конструкцией RESTART WITH.

Значение должно быть в пределах допустимого диапазона объявленного типа. Далее последовательность начнется с указанного значения, не со следующего.

Т.е. если задать

 

А потом выполнить скрипт:

То результат будет таким:

Последовательность началась с заданного значения.

Получить минимальные и максимальные значения можно из каталога sys.sequences.

MIN и MAX значения

Для последовательностей можно задавать границы допустимых значений. Попробуем выполнить такой скрипт ниже.

Минимальное значение равняется 10, максимальное – 20, но мы пытаемся задать начальное значение равное единице. Это за пределами допустимого диапазона и поэтому нас порадуют сообщением:

The start value for sequence object ‘GenerateNumberSequence’ must be between the minimum and maximum value of the sequence object.

Далее можем представить, что следующее значение в последовательности нарушает границу. В таком случае получим ошибку:

The sequence object ‘GenerateNumberSequence’ has reached its minimum or maximum value. Restart the sequence object to allow new values to be generated.

Для решения проблемы есть два пути:

  • Использовать служебные слова Restart или Restart With.
  • Использовать опцию CYCLE

Опция CYCLE

Данная опция зацикливает последовательность и, достигнув максимального значения, последовательность продолжается с минимального. Например:

 

После того как максимальное значение было достигнуто, результаты станут такими:

Для выборки использовался запрос:

Если внимательно посмотреть на вывод, то можно заметить, что записи были перепутаны. Если бы мы не использовали последовательности, то вывод был бы

Но из-за того, что вторая запись пересекла диапазон допустим значений, номер был сброшен на минимальное значение, заданное для последовательности (10). Если сейчас посмотреть в каталог sys.sequences, то будет видно, что текущее значение равняется 10.

В следующий раз, заполнение таблицы могло бы быть таким:

В этот момент Sequence проверит порядок в котором записи будут вставлены и так как “Violet” идет раньше “Tape” и текущий номер равен 10, записи будут вставлены как:

Следующее_занчение =Текущее_значение +Сдвиг т.е. 10 +1 будет присвоено для  “Violet”. Теперь значение Sequence = 11 и для второй записи значение будет 12 следуя то же самой формуле.

Опция NO CYCLE

Поведение такой опции уже рассматривалось в самом начале, и является значением по умолчанию при создании Sequence.

Sequence в сочетании с Over()

Можно использовать последовательность вместе с выражением Over для генерирования порядковых номеров как показано ниже:

Результат:

Можно заметить, что записи были отсортированы и последовательность была применена верно к сохраненным данным. Это означает, что записи сначала сортируются и только потом применяется нумерация последовательности.

Ограничения использования Next Value для функций.

Sequence ни в каких случаях нельзя использовать в сочетании с:

  • Проверкой ограничений (constraints)
  • Значениями по умолчанию
  • Вычисляемыми колонками
  • Представлениями (views)
  • Пользовательскими функциями
  • Пользовательскими функциями агрегации
  • Подзапросами
  • СТЕ (Common Table Expression)
  • Подтаблицами
  • Выражением TOP
  • Выражением Over
  • Выражением  Output
  • Выражением On
  • Выражением Where
  • Выражением Group By
  • Выражением Having
  • Выражением Order By
  • Выражением Compute
  • Выражением Compute By

Функция sp_sequence_get_range

Если рассмотреть все использованные выше подходы к добавлению строк в таблицы используя NEXT VALUE FOR, то становится заметно, что это выражение присутствует в каждом уровне VALUES, что выглядит несколько утомительно. Вместо этого можно использовать функцию sp_sequence_get_range для получения необходимого диапазона значений, которые можно использовать впоследствии. Сейчас продемонстрирую как это можно осуществить.

Вот что будет в результате выполнения:

Здесь можно увидеть, что последовательность была увеличена до 1000 и пропущенные значения не были использованы нигде без нашего ведома. В данном случае мы их использовали для вставки значений.

Сравнение между Sequence и Identity

Не стоит ставить между ними глобальный знак равенства из-за следующих факторов:

  • Identity относится к таблице и является ее частью неотделимой, Sequence – независимый объект базы данных.
  • Можно получить набор последовательности с помощью sp_sequence_get_range, что в принципе невозможно с Identity.
  • Для Sequence можно определять границы значений, что так же невозможно для Identity.
  • Цикличность значений можно задать так же только для Sequence.

И еще несколько слов про Sequence.

  • Sequence дает больший прирост производительности по сравнению с Identity. Сравнение и результаты в статье Аарона Бертарнда (Aaron Bertrand)
  • Можно задавать права доступа к Sequence, так же как и к другим объектам базы.

Почитать дополнительно о Sequence можно на MSDN:

  1. CREATE SEQUENCE
  2. Creating and Using Sequence Numbers
  3. sp_sequence_get_range

 

Дальше будет так же интересно, так что оставайтесь на связи. Перевод.

Hard’n’heavy!