Posted on 28. January 2019

Больше возможностей с шаблонами в C# 8.0

Больше возможностей с образцами в C# 8.0

Вышел второй предварительный просмотр Visual Studio 2019! Наряду с ним были разработаны дополнительные C# 8.0 функции. В основном в данной статье речь пойдет о новых образцах, хотя в конце также будут рассмотрены другие новости и изменения.

Еще больше образцов

Когда в C# 7.0 была добавлена поддержка образцов, Microsoft объявили, что собираются добавить еще больше образцов в большем количестве знаков. Это время настало! Добавляются так называемые рекурсивные образцы, а также более компактная форма оператора switch выражений, называемых (как Вы уже догадались) switch выражениями.

Вот простой пример образцов C# 7.0:

class Point
{
    public int X { get; }
    public int Y { get; }
    public Point(int x, int y) => (X, Y) = (x, y);
    public void Deconstruct(out int x, out int y) => (x, y) = (X, Y);
}

static string Display(object o)
{
    switch (o)
    {
        case Point p when p.X == 0 && p.Y == 0:
            return "origin";
        case Point p:
            return $"({p.X}, {p.Y})";
        default:
            return "unknown";
    }
}

Switch выражения

Следует отметить, что многие switch выражения на самом деле не выполняют в case основах ничего особенного. Часто они просто создают значение, либо присваивая его переменной, либо возвращая его (как указано выше). Во всех этих случаях switch выражение выглядит довольно неуклюже и напоминает язык пятидесятилетней давности, очень церемонный и громоздкий.

Поэтому пришло время добавить форму выражения switch. См. пример:

static string Display(object o)
{
    return o switch
    {
        Point p when p.X == 0 && p.Y == 0 => "origin",
        Point p                           => $"({p.X}, {p.Y})",
        _                                 => "unknown"
    };
}

Ниже приведены отличия от switch операторов:

  • Ключевое слово switch – это «infix» между проверенным значением и {...} списком случаев. Это делает данное слово более совместимым с другими выражениями, а также позволяет отличить его визуально от switch оператора.
  • Ключевое слово case и «:» символ для краткости были заменены лямбда-стрелкой =>.
  • Default значение для краткости было заменено _ шаблоном сброса.
  • Атрибуты bodies – это выражения! Результат выбранного атрибута становится результатом switch выражения.

Поскольку выражение должно иметь значение или выдавать исключение, то switch выражение, которое доходит до конца без совпадений, генерирует исключение. Компилятор предупреждает, когда это может произойти, но не заставляет останавливать все switch выражения с помощью catch-all сервиса: ведь Вы знаете лучше!

Теперь, когда Display метод состоит из только одного return оператора, можно упростить его до состояния выражения:

static string Display(object o) => o switch
    {
        Point p when p.X == 0 && p.Y == 0 => "origin",
        Point p                           => $"({p.X}, {p.Y})",
        _                                 => "unknown"
    };

Этот путь более лаконичный и понятный, ведь, как указано выше, именно краткость позволяет форматировать «табличным» способом switch, с шаблонами и телами на одной линии, где => выстроились друг под другом.

Microsoft планирует разрешить использование «,» запятой после последнего кейса в соответствии со всеми другими «разделенными запятыми списками в фигурных скобках» в C#, но во втором предварительном просмотре Visual Studio 2019 осуществить это пока нельзя.

Образцы свойств

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

Обратите внимание, что switch выражение использует Point p тип шаблона (дважды), а также when предложение для добавления дополнительных условий для первого case.

 В C# 8.0 Microsoft добавляет дополнительные необязательные элементы в тип образца, что позволяет самому образцу углубиться в значение сопоставляемого шаблона. Его можно сделать шаблоном свойства, добавив {...}, который содержит вложенные шаблоны, для применения к доступным свойствам или полям значения. Это позволяет переписать switch выражение следующим образом:

static string Display(object o) => o switch
{
    Point { X: 0, Y: 0 }         p => "origin",
    Point { X: var x, Y: var y } p => $"({x}, {y})",
    _                              => "unknown"
};
Оба случая все еще проверяют, что o является Point. В первом случае 0 шаблон константы применяется рекурсивно к X и Y свойствам переменной p, проверяя, есть ли у них это значение. Таким образом, when условие может быть исключено в данном и многих распространенных случаях.

Во втором случае var шаблон применяется к каждому из X и Y. Стоит напомнить, что выполнение var шаблона в C# 7.0 всегда завершается успешно и просто объявляет новую переменную для хранения значения. Таким образом, x и y содержат значения int для p.X и p.Y.

p никогда не используется, а значит, фактически его можно опустить и здесь:

Point { X: 0, Y: 0 }         => "origin",
    Point { X: var x, Y: var y } => $"({x}, {y})",
    _                            => "unknown"
То, что остается верным для всех типов образцов, включая образцы свойств, – это их ненулевое значение. Благодаря чему становится возможным использование «пустого» {} свойства образца в качестве компактного «ненулевого» шаблона. Например, запасной вариант можно заменить следующими двумя двумя кейсами:

{}                           => o.ToString(),
    null                         => "null"

Позиционные образцы

Образец свойств не совсем укорачивает второй Point кейс, но в данном случае можно сделать многое.

Обратите внимание, что у Point класса есть Deconstruct метод, так называемый deconstructor. В C# 7.0 деконструкторы позволяли деконструировать значение при присваивании, чтобы можно было написать код такого плана:

(int x, int y) = GetPoint(); // split up the Point according to its deconstructor
В C# 7.0 деконструкция с использованием образцов интегрирована не была. Это меняется с позиционными образцами, которые являются дополнительным способом расширения шаблонов типов в C# 8.0. Если совпавший тип является типом кортежа или у него есть деконструктор, то можно использовать позиционные шаблоны как компактный способ применения рекурсивных шаблонов без необходимости называть свойства:

static string Display(object o) => o switch
{
    Point(0, 0)         => "origin",
    Point(var x, var y) => $"({x}, {y})",
    _                   => "unknown"
};

Как только объект сопоставлен с Point, применяется деконструктор, а вложенные шаблоны применяются к результирующим значениям.

Использование деконструкторов не всегда уместно. Их следует добавлять только к тем типам, где значения объяснимы и бесспорны. Например, для Point класса первое значение – X, а второе – Y очевидны, поэтому приведенное выше switch выражение интуитивно понятно и легко читается.

Образцы кортежей

Очень полезный особый случай позиционных образцов – их применение к кортежам. Если switch оператор применяется непосредственно к выражению кортежа, то разрешено опустить дополнительный набор скобок, как в switch (x, y, z) вместо switch ((x, y, z)).

Шаблоны кортежей отлично подходят для одновременного тестирования нескольких входных данных. Ниже приведена простая реализация стейт-машины:

static State ChangeState(State current, Transition transition, bool hasKey) =>
    (current, transition) switch
    {
        (Opened, Close)              => Closed,
        (Closed, Open)               => Opened,
        (Closed, Lock)   when hasKey => Locked,
        (Locked, Unlock) when hasKey => Closed,
        _ => throw new InvalidOperationException($"Invalid transition")
    };

Конечно, можно было бы добавить hasKey во включенный кортеж вместо использования when предложений, но это действительно вопрос вкуса:

static State ChangeState(State current, Transition transition, bool hasKey) =>
    (current, transition, hasKey) switch
    {
        (Opened, Close,  _)    => Closed,
        (Closed, Open,   _)    => Opened,
        (Closed, Lock,   true) => Locked,
        (Locked, Unlock, true) => Closed,
        _ => throw new InvalidOperationException($"Invalid transition")
    };

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

Другие функции C# 8.0 во Втором Предварительном Просмотре

Несмотря на то, что во втором предварительном просмотре VS 2019 основные функции для работы с образцами являются наиболее важными, есть несколько более мелких особенностей, которые не менее полезны и интересны. Ниже приведено краткое описание каждой.

Using объявления

В C# using операторы всегда приводят к вложенности, что может сильно раздражать и ухудшать читабельность. Для простых случаев, когда нужно, чтобы ресурс был очищен в конце области, теперь используются using объявления. Using объявления – это объявления локальных переменных с ключевым словом using в начале, где их содержимое располагается в конце текущего блока операторов. Так что вместо:

static void Main(string[] args)
{
    using (var options = Parse(args))
    {
        if (options["verbose"]) { WriteLine("Logging..."); }
        ...
    } // options disposed here
}

Можно написать следующее

static void Main(string[] args)
{
    using var options = Parse(args);
    if (options["verbose"]) { WriteLine("Logging..."); }

} // options disposed here
Disposable ref структуры

Ref Структуры были введены в C# 7.2, полезные функции которых были рассмотрены в других статьях. Стоит отметить, что они накладывают некоторые серьезные ограничения, такие как невозможность реализации интерфейсов. Ref структуры теперь доступны без реализации Idisposable интерфейса, просто с помощью Dispose метода.

Статические локальные функции

Чтобы убедиться, что выполнение локальной функции не забирает много времени, связанного с «захватом» (ссылками) переменных из охватывающей области, можно объявить ее как static. Тогда компилятор устранит ссылку на все, что объявлено во вложенных функциях, кроме других статических локальных функций.

Изменения с момента выпуска Первого Предварительного Просмотра

Основными функциями Первого Предварительного Просмотра были обнуляемые ссылочные типы и асинхронные потоки. Обе версии были немного изменены во Втором Выпуске, поэтому перед началом использования полезно знать следующее.

Обнуляемые ссылочные типы

Microsoft добавили больше опций для управления пустыми предупреждениями как в источнике (через #nullable и #pragma warning директивы), так и на уровне проекта. Также была изменена подписка на файл проекта к enable .

Асинхронные потоки

Microsoft изменила форму IAsyncEnumerable интерфейса, которую ожидает компилятор. Это приводит к тому, что компилятор не синхронизируется с интерфейсом, предусмотренным в .NET Core 3.0 Preview 1, что может привести к некоторым проблемам. Однако планируется выпуск .NET Core 3.0 Preview 2, который вернет синхронизацию интерфейсов.

Обратите внимание

Microsoft ждет Ваших отзывов! Попробуйте новые особенности. 


 




Posted on 22. December 2018

Ознакомление с Project Mu

Команда Microsoft Devices Team объявляет о выпуске Project Mu, версии с открытым исходным кодом на базе Unified Extensible Firmware Interface (UEFI) ядра, основанного на Microsoft продуктах, включая Surface и последние версии Hyper-V. UEFI – это системное программное обеспечение, которое инициализирует оборудование во время процесса загрузки и предоставляет сервисы для загрузки операционной системы. Project Mu предоставляет собой множество UEFI функций, предназначенных для современных ПК под управлением Windows. Он также показывает структуру кода и процесс разработки для эффективного использования масштабируемой и надежной прошивки. Эти изменения позволяют Project Mu устройствам поддерживать микропрограмму в виде (FaaS) сервиса. Схожая по своей сути «Windows как сервис», «Прошивка как сервис» оптимизирует UEFI и другие системные прошивки для своевременных исправлений качества, которые обновляют прошивку и обеспечивают эффективную разработку функций сразу после запуска.

Использование встроенного программного обеспечения в качестве открытого источника

При первом включении FaaS в Surface было обнаружено, что TianoCore реализация с открытым UEFI исходным кодом не была оптимизирована для быстрого обслуживания для нескольких линейек продуктов. Были проведены несколько итераций продукта на FaaS, а в результате опубликован бесплатный проект с открытым исходным кодом - Project Mu!

Функции проекта

Project Mu включает в себя:

  • Структуру кода и процесс разработки, оптимизированный под прошивку как сервис.
  • Экранную клавиатуру.
  • Безопасное управление UEFI настройками.
  • Повышенную безопасность за счет удаления ненужного устаревшего кода; практика, которая используется для уменьшения зоны атаки.
  • Высокоэффективную загрузку.
  • Примеры современного BIOS меню.
  • Многочисленные тесты и инструменты для анализа и оптимизации качества UEFI.

Материал для ознакомления с документацией и кодом Project Mu Вы найдете по ссылке: https: //microsoft.github.io/mu/ 



Posted on 7. June 2010

Бизнес-возможности Windows Phone 7

Сегодня компания Microsoft опубликовала большой пост посвященный обсуждениям бизнес-функциям телефона с платформой Windows Phone 7 на борту. Тем самым компания хочет показать, что хотя платформа ориентирована на конечных пользователей, "бизнес-пользователи" также не останутся без внимания. Часть поста:

 Большинство людей, при выборе смартфона, учитывают необходимый набор задач решаемых с помощью устройства. Учитывая это, мы часто слышым от ИТ-специалистов, что наиболее важным фактором для смартфонов является его функциональность как для каждого человека лично так и для ИТ-организации в целом. Компании заинтересованы в сохранении вложеных инвестиций (например Exchange, SharePoint, Office). Windows Phone 7 поддерживает необходимые возможности для ИТ компаний, без использования дополнительной инфраструктуры. Особенно, Windows Phone 7:

  • создан с нуля, используя лучшие практики в разработке безопасного программного обеспечения(Secure Development Lifecycle).
  • сильно интегрирован с эл. почтой, календарем и контактами с Exchange Server. Тем самым упрощая взаимодействие с эл. почтой и управление календарем. Что в свою очередь повышает продуктивность.
  • интегрирован с SharePoint используя SharePoint Workspace клиента.
  • помогает защитить корпоративные данные используя PIN и пароль для безопасности.
  • помогает обеспечить достоверность данных и целосность путем использования песочницы управляемого кода
  • обеспечивает проверку сертификации, приложений и контента через Windows Marketplace
  • обеспечивает безопасную передачу данных с использованием 128-ми или 256-ти Bit SSL-шифрования.
  • поддержка защищенного доступа
  • в дальнейшем будет интегрирован с облаками/сервисами.

Оригинал поста



Posted on 27. May 2010

Рост Silverlight технологии

На одном из мероприятий меня спросили, где можно посмотреть полный список возможностей каждой версии Silverlight расширения. Вот таблица возможностей Silverlight'а в каждой его версии:

 Silverlight Versions
Features 1.0 2 3 4
Cross-Browser Support for Firefox, IE, Safari
Cross-Platform Support for Windows and Mac (and Linux through the Moonlight Project)
2D Vector Animation/Graphics
AJAX Support
HTML DOM Integration
HTTP Networking
Canvas Layout Support
JavaScript Support
XAML Parser
Media – 720P High Definition (HD) Video
Media – Audio/Video Support (VC-1, WMV, WMA, MP3)
Media – Image Support (JPG, PNG)
Media - H.264 video and AAC audio Support    
Media Markers
Windows Media Server Support
Support for Visual Basic.NET and C#; Common Language Runtime (CLR) based languages  
Support for IronPython, IronRuby, Managed JScript, and other Dynamic Language Runtime (DLR) based languages  
Rich Core Framework (e.g. Generics, collections)  
Multi-Threading  
Layout controls including StackPanel and Grid  
Full suite of Controls (TextBox, RadioButton, Slider, Calendar, DatePicker, DataGrid, ListBox, TabControl, and others)  
Managed Control Framework  
Templating Model  
Visual State Manager  
Isolated Storage  
Deep Zoom Technology  
Media – DRM Powered by PlayReady  
Media - Windows Media Audio 10 Professional support  
Media - MediaStreamSource for managed code media file parser and protocol extensibility  
High quality resizing  
Media - Basic SSPL Support  
Cross Domain Network Access  
Easy access to server-side data via Web Services  
Direct access to TCP sockets  
Interoperability with SOAP and REST services, including support for XML, JSON, RSS and Atom data formats  
LINQ (including LINQ to XML, LINQ to JSON, and LINQ to Entities)  
Duplex communications (“push” from Server to Silverlight client)  
Data Binding  
WCF Data Services  
Managed HTML Bridge  
Managed Exception Handling  
.NET Framework Security Enforcement  
Type Safety Verification  
XMLReader/Writer  
Enhanced Keyboard Input Support  
File Upload Support (via WebClient API)  
WPF Compatibility  
Accessibility  
Localization  
Remote Debugging (PC and Mac)  
Out of Browser    
Network Status (Offline)    
Pixel Shader Effects    
Bitmap API    
Theming at runtime    
Enhanced Control Skinning    
Accessibility - System Colors    
Bitmap caching    
Perspective 3D    
GPU Hardware Acceleration (for video and bitmaps)    
Text Animation    
Raw A/V Support    
File Save Dialog    
DockPanel, WrapPanel, Viewbox    
Element to Element Binding    
Local Connection    
Binary XML    
Component Caching (share resources across apps)    
Scene caches (to Bitmap)    
Local Fonts      
Printing      
WCF RIA Services      
Managed Extensibility Framework (MEF)      
Webcam      
Microphone      
Official Support for Google Chrome      
Output Protection for audio/video      
Multicast networking      
Offline DRM      
Trusted Applications (extended sandbox)      
IDispatch COM Interop      
Group policy object support      
Full keyboard in out-of-browser for trusted applications      
Cross-domain network access for trusted applications      
Custom window chrome      
Out of browser window settings (position, size etc.)      
Web Browser Control and Web Browser Brush      
Notification Toast      
Right-to-Left / BiDi Text      

 Источник