Visual Basic

14 основных усовершенствований в Visual Basic 14

Лучиан Вишик

Продукты и технологии:

Visual Basic 14, Visual Studio 2015

В статье рассматриваются:

  • более эффективная среда кодирования;
  • усовершенствованные основы системы проектов;
  • улучшения в языковых средствах.

Visual Basic 14 — самая новая версия Visual Basic, и она будет поставляться как часть Visual Studio 2015. В этой версии были заново переписаны 1,3 миллиона строк кода VB — более ранние версии в основном писались на C++. Группа воспользовалась предоставленной возможностью и подвергла полной ревизии все части VB. Я попросил группу отобрать главные 14 усовершенствований. И все они сошлись во мнении, что главные усовершенствования лежат в области кодирования, основах системы проектов и в самом языке.

Более эффективная среда кодирования

1. Рефакторинг «Один лишь факт, что мы наконец сумели встроить непосредственно в этот продукт поддержку рефакторинга, уже имеет колоссальное значение». — Джим Вули (Jim Wooley), MVP в области .NET

Нередко бывало, что вам приходилось покупать дополнительные продукты только для того, чтобы получить важные доработки для Visual Basic вроде извлечения метода или подстановки временной переменной. Для C# было несколько таких доработок, и Microsoft в сотрудничестве с Developer Express сделала доступной свою надстройку Refactor! пользователям Visual Basic в Visual Studio 2005. Теперь возможности рефакторинга встроены в Visual Studio 2015! Чтобы задействовать их, щелкните какой-нибудь идентификатор или выделите sub-выражение. Затем нажмите Ctrl+. или щелкните правой кнопкой мыши и выберите Quick Actions. Это приведет к открытию контекстного меню с релевантными операциями, как показано на рис. 1.

Visual Basic 14 теперь имеет встроенные средства рефакторинга
Рис. 1. Visual Basic 14 теперь имеет встроенные средства рефакторинга

Заметьте, что средства рефакторинга контекстно-зависимы. Например, если вы извлечете правую часть выражения «Dim circleArea = Math.PI * radius * radius» в какой-либо метод, Visual Basic предложит для этого метода имя GetCircleArea. И переключится в режим переименования, если вы хотите изменить это имя. Этот режим весьма интеллектуален, поскольку способен распознавать и предупреждать вас о конфликтах имен, если вы выберете уже используемое имя; при этом данный механизм действует в пределах всего решения, даже при изменении имен в проектах на C#.

2. Анализаторы «Впечатляют. У меня столько идей насчет того, как использовать их,… я часто вижу много досадных мелочей в коде программистов». — Случайно услышано от одного MVP в области Windows PowerShell

Анализаторы — это способ выявления ошибок в вашем коде. Их можно использовать для введения в действие правил кодирования в рамках группы. Если вы столкнулись с проблемой, требующей отладки, то можно подключить анализатор, чтобы быстро найти дефекты кода во всем решении. А многие используемые вами библиотеки могут стать «осведомленными о коде» («code-aware») с помощью собственных встроенных анализаторов. Допустим, вы еще не пользовались библиотекой Microsoft Azure Storage или не читали статьи с соответствующими рекомендациями. Так как библиотека теперь поставляется с анализатором, который обнаруживает распространенные изъяны в применении ее API, вы сможете немедленно узнать, правильно ли вы ее используете. Словно за вашей спиной стоит эксперт, оценивающий ваш код по мере его набора.

Вы можете добавлять анализаторы в свой проект в новом узле References | Analyzers (или через NuGet). Как только они становятся частью вашего проекта, набранный с ошибкой код подчеркивается волнистой линией. Они запускаются при сборке проекта в Visual Studio или из командной строки и работают даже применительно к серверам сборок. Анализаторы дают шанс раскрыть внутренности компилятора, чтобы увидеть синтаксические деревья исходного кода проекта, его типы и члены. Разработчики будут приятно удивлены тому, насколько легко включать в анализаторы свои экспертные знания; все это стало возможным благодаря этим синтаксическим деревьям и типам с членами. Мой любимый анализатор — тот, который обнаруживает, где моя группа использует методы Async Sub, которые должны быть Async Function…As Task, и выдает предупреждение. Это острый угол асинхронного программирования, о котором знают не все и который ведет к трудноуловимым ошибкам параллельной обработки, поэтому важно, чтобы моя группа могла отлавливать ошибку при компиляции. Чтобы приступить к написанию собственных анализаторов, отправляйтесь на сайт roslyn.codeplex.com.

3. Уводить курсор со строки больше не требуется «Теперь мы делаем правильно». — Дастин Кемпбелл (Dustin Campbell), член группы Visual Basic

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

Теперь вам не нужно этого делать. Просто оставьте курсор, где он есть, и волнистая линия сама появится в случае ошибки или исчезнет после правки.

4. Ссылки в документирующих XML-комментариях «Для тех, кто увлекается такой документацией, это колоссальный шаг в правильном направлении». — Сэм Харуелл (Sam Harwell), MVP в области .NET

Вы увлекаетесь документирующими XML-комментариями (XML doc comments)? Вот небольшой пример:

''' <summary>
''' Similar to <see cref="List(Of Integer).Count"/>
''' </summary>
''' <param name="e">Thing to count</param>
''' <remarks></remarks>
Sub Count(e As IEnumerable)
End Sub

В предыдущих версиях VB, когда вы вводили cref и param-name в своих комментариях, вы получали список для выбора завершающих строк, но, помимо этого, вы были предоставлены сами себе. Компилятор выполнял минимальную проверку на существование таких имен, но они выводились серым цветом, и их было нелегко найти или исправить.

Теперь в Visual Basic 14 аргументы cref и param-name окрашиваются в должные цвета. Вы можете задержать над ними курсор мыши и увидеть всплывающие подсказки. При рефакторинге символов с изменением их имен (Ctrl+R, Ctrl+R) Visual Basic переименовывает все ссылки на символ, включая те, что находятся в cref и param-name. Вы можете щелкнуть один из них правой кнопкой мыши и выбрать Go to Definition или Find All References. Если вы хотите сослаться на метод, имеющий несколько перегрузок, то теперь можете однозначно указать на нужную вам перегрузку. Все эти изменения упрощают набор ссылок в документирующих XML-комментариях и избавляют от ошибок.

Основы системы проектов

5. Узел References в Solution Explorer «Реальность такова, что изменять ссылки приходится ежедневно». — Лучиан Вишик (Lucian Wischik), член группы Visual Basic

На рис. 2 показано, как выглядит типичный проект Visual Basic 14 в Solution Explorer.

Узел References теперь показывается в Solution Explorer
Рис. 2. Узел References теперь показывается в Solution Explorer

Новинкой является узел References. Раньше он был скрыт, и приходилось щелкать Show All Files, чтобы увидеть его, но попутно отображалось множество нерелевантных файлов.

Прежнее поведение имело смысл 10 лет назад, когда вы начинали с проекта Windows Forms, и в нем, как правило, был правильный набор ссылок. Но реальность современной разработки в том, что теперь часто используется узел References — особенно для управления NuGet-ссылками. Это небольшое, но очень удобное новшество, позволяющее быстро найти нужные ссылки в Solution Explorer.

6. Общие проекты «Это по-настоящему замечательный инструментарий поверх связанных файлов, благодаря которому с ними легче работать». — Мортен Нильсен (Morten Nielsen), MVP в области Windows Developer

Допустим, вы хотите сделать какой-то код общим для двух или более проектов. Это достаточно распространенная ситуация, например при поддержке двух версий приложения — для Windows Presentation Foundation (WPF) и Windows Phone. Цель всегда одна и та же: в максимальной мере повторно использовать код, чтобы, например, исправление ошибки в одном проекте автоматически распространялось на другой проект.

В прошлом вы могли выбирать один из двух методов: использовать связанные файлы для совместного использования общего кода или изменить архитектуру общего кода и поместить его в Portable Class Library (PCL), чтобы пользоваться общей двоичной библиотекой. Теперь в Visual Basic 14 предлагается третий, очень эффективный метод: Shared Projects.

Зачем использовать Shared Projects? Задача совместного использования кода непроста, и у нее нет хорошего решения на все случаи. PCL — хорошее и ясное решение, но это заставляет вас проектировать общий код так, чтобы он никогда не вызывал что-либо из проектов WPF или Phone; допускаются лишь вызовы системных API, присутствующих как в WPF, так и в Phone. Shared Projects проще в использовании, так как они не требуют переработки архитектуры общего кода.

Чтобы подготовить общий проект, щелкните правой кнопкой мыши свое решение и выберите Add | New Project | VB | Shared Project. Затем поочередно щелкайте правой кнопкой мыши узел Reference каждого проекта и выбирайте Add | Shared Projects. Общий проект является просто набором файлов исходного кода, XAML-файлов, изображений и других ресурсов, которые будут включаться в каждый проект, который ссылается на данный проект.

Для каждого из проектов вы также можете настроить My Project | Compile | Advanced Compile Options | Custom Constants с помощью пользовательских констант, например WPF и PHONE. Затем в общем коде можно вызывать специфичные для проекта API:

#If WPF Then
  ' nothing needed
#ElseIf PHONE Then
  ShowBatteryStatus()
#End If

7. Ускорение компиляции на 50% «50% — это не шутки». — Сэм Наруэлл (Sam Harwell), MVP в области .NET

Обычно компилятор Visual Basic писали на C++. В случае Visual Basic 14 группа переписала его полностью на VB, что сделало его значительно быстрее работающим! Вот два сравнения:

  • время сборки крупного проекта (1,3 миллиона строк кода) сократилось с 68 секунд до 41;
  • время первой загрузки решения (приложения Windows Store) уменьшилось с 6,7 секунд до 4,6.

Это значительная экономия времени.

Увеличение производительности на 50% может оказаться сюрпризом для тех, кто считает, что C++ быстрее VB. Истина в том, что реально выигрыш по скорости вы получаете в работе с алгоритмами, структурами данных и в параллельной обработке. Прирост производительности от переписывания на VB складывается из многих составляющих: пересмотра структур данных, возможности более ясного выражения алгоритмов и более безопасного рефакторинга, применения асинхронности, пула потоков и средств профилирования Visual Studio для выявления чрезмерной нагрузки на процессор и слишком большого выделения памяти, а также использования анализаторов для обнаружения простых «подводных камней», влияющих на производительность .NET, например ненужной упаковки (boxing).

8. Лямбды и LINQ-выражения в окне Watch «Великолепно!» — Мнение Марко Зенн-Хаага (Marco Senn-Haag), пользователя Visual Studio Uservoice

LINQ и лямбды — отличный способ получения итоговых данных. Одна из областей, где это необходимо чаще всего, — отладка с помощью окон Watch и Immediate. В прошлом любые попытки использования здесь LINQ или лямбд приводили к ошибке:

Evaluation of lambda expressions is not valid in the debugger.

Теперь, как видно на рис. 3, это просто работает! Например, если вы остановились на точке прерывания, где у вас есть набор customers, вы можете быстро считать набор, написав в окне Watch такой запрос:

From c In customers Where c.OrderStatus = "Unfulfilled" Select c.LastName

Лямбды и LINQ-выражения в окне Watch
Рис. 3. Лямбды и LINQ-выражения в окне Watch

Знали ли вы, что окно Immediate можно использовать даже без запуска вашей программы? Скажем, если вы только что написали некий модуль с функцией GetName, то можете открыть окно Immediate (Debug | Windows | Immediate), ввести «? GetName()» и получить значение функции.

Visual Studio 2015 также обеспечит более качественную поддержку функции Edit and Continue (правка кода и продолжение работы программы), в частности в методах Async и Iterator, а также в более распространенных ситуациях, например внутри LINQ-запросов и лямбд, позволяя даже добавлять в существующий метод новый запрос или лямбда-выражение. Хотя этого пока нет в Visual Studio 2015 Preview, в финальной версии все это появится.

9. Более ясный список ошибок «Что было раньше и что есть сейчас — это действительно большая разница». — Энтони Д. Грин (Anthony D. Green), член группы Visual Basic

В Error List в Visual Basic 14 внесен ряд практичных улучшений, отвечающих давно поступавшим запросам от пользователей (рис. 4). Раньше Error List показывал полные имена типов, а теперь выводит лишь минимально дополненные имена типов, чтобы вам было легче читать сообщение об ошибке. Кроме того, отображается код ошибки, что удобно для сортировки по кодам ошибок. Еще важнее, что код ошибки является гиперссылкой для поиска в Интернете, что зачастую гораздо полезнее, чем ссылка на страницу документации MSDN. Вы также можете фильтровать каждый столбец в списке ошибок подобно тому, как это делается в Excel.

Error List в Visual Studio 2015 (внизу) более читаемый и гибкий, чем в Visual Studio 2013 (вверху)
Рис. 4. Error List в Visual Studio 2015 (внизу) более читаемый и гибкий, чем в Visual Studio 2013 (вверху)

Иногда при внесении крупных изменений легко вогнать решение в такое состояние, где ломается масса ниже расположенного кода. В прошлом VB показал бы только первые 101 ошибок. Это затрудняло понимание того, насколько обширно повлияло разрушающее изменение, или получение представления о том, какого рода изменения вам следовало бы внести. Теперь Visual Basic 14 отображает все ошибки без ограничений. (Это можно настроить в Tools | Options | Text Editor | Basic | Advanced | Show diagnostics для закрытых файлов.)

Языковые улучшения

10. Операторы распространения null «Постоянная потребность в проверках на null выходит боком как в отношении производительности, так и вероятности ошибок». — Дебора Курата (Deborah Kurata), MVP в области .NET

Допустим, у вас есть класс Customer с полем Address, которое вполне может содержать null, возможно, из-за того, что ваше приложение не требует заполнения адресов. Ранее любой код, который должен был что-то делать с адресом, например показывать его пользователю, нужно было защищать проверкой на null. Такие проверки очень быстро становятся утомительными. В Visual Basic 14 вы можете изящно обрабатывать вероятность содержания null, используя новый оператор?.:

Console.WriteLine("{0} ({1})",
  customer.Name,
  customer.Address?.Country)

Оператор ?. — это просто сокращение для распространенного, но громоздкого шаблона присваивания временной переменной и последующей проверки ее значения на null:

Dim _temp = customer.Address
Console.WriteLine("{0} ({1})",
  customer.Name,
  If(_temp Is Nothing, Nothing, _temp.Country))

Вы можете использовать ?. в последовательности и смешивать его с обычным оператором-точкой, например a?.b.c?.d. Читается последовательность слева направо. Любое null-значение, используемое ?., остановит последовательность и даст ответ Nothing, того как любое null-значение, используемое оператором-точкой, сгенерирует, как обычно, исключение NullReferenceException.

Оператор ?. является null-условной версией оператора-точки. Существуют такие версии и для большинства других операторов: индексации — array?(i), вызова делегата — delegate?(args), поиска в словаре — dict?!key и axis-свойства XML — xml?.@attr, xml?.<key>, xml?...<key>.

Вы также можете использовать ?. и другими удобными способами:

If customer?.Age > 50 Then ...
' Эта ветвь срабатывает, только если customer
' не равен null и старше 50

Dim name = If(customer?.Name, "blank")
' Выбираем имя по умолчанию, если customer - null

Dim first = customers?.FirstOrDefault()
' Этот метод вызывается, только если customers не равен null

11. Многострочные строковые литералы «Печально ли, что я так рад многострочным строковым литералам?» — Scaramouche, пользователь одного из форумов

Вот как вы привыкли писать многострочные строки, приперченные vbCrLf:

Dim json = "{" & vbCrLf &
"  'Name': 'Bad Boys'," & vbCrLf &
"  'ReleaseDate': '1995-4-7T00:00:00'," & vbCrLf &
"  'Genres': ['Action','Comedy']" & vbCrLf &
"}"

Понятно, что многие просили ввести поддержку строковых литералов, охватывающих несколько строк. Теперь в Visual Basic 14 можно писать так:

Dim json = "{
  'Name': 'Bad Boys',
  'ReleaseDate': '1995-4-7T00:00:00',
  'Genres': ['Action','Comedy']
}"

Связанная с ней значимая функция, о которой тоже часто просили, — размещение комментариев в многострочных выражениях. Ранее они были недопустимы в LINQ-выражениях наподобие следующего:

Dim q = From x In y ' This is a from clause
        Where x < z ' And this is the where
        Select x    ' This select is redundant

12. Подстановка строк «Эта функция намного упрощает код и проясняет ваши намерения». — Judah, пользователь Channel9

Подстановка строк (string interpolation) — более простой способ написания строк с выражениями внутри них:

Dim s = $"hello {p.Name} you are {p.Height:0.00}m tall"

Это лишь сокращение следующего:

Dim s = String.Format("hello {0} you are {1:0.00}m tall", p.Name, p.Height)

Подставлять строки зачастую проще, чем явно вызывать String.Format, поскольку это избавляет вас от необходимости расстановки позиционных символов подстановки {0} и {1}. И конечно, для этих прогалов в выражении обеспечивается полная поддержка IntelliSense и цветовых выделений. Подстановка строк особенно хорошо работает с программно формируемыми строками, как в этих примерах:

Dim fn = $"C:\Documents\{folder}\{file}.{ext}"
Dim url = $"http://{site}/{path}/{file}?search={query}"

Как и при использовании String.Format, это выражение форматирует строку с учетом текущей культуры. Если вы программно формируете строку, которая включает числа с плавающей точкой, например при передаче долготы и широты веб-сервису, вы скорее всего предпочтете InvariantCulture. Это будет поддерживаться в Visual Studio 2015, но на момент выхода этой статьи такая поддержка еще прорабатывается.

Заметьте, что подстановки строк пока нет в Visual Studio 2015 Preview, но она появится в финальной версии Visual Studio 2015.

13. NameOf «Это будет большой помощью во многих сценариях». — ewwloyd, участник форума Roslyn

Оператор NameOf — более эффективный способ встраивания строкового литерала в код, когда этот литерал ссылается на какое-то имя в вашем исходном коде. Вот лишь один пример:

Sub f(s As String)
  If s Is Nothing Then Throw New ArgumentNullException(NameOf(s))
End Sub

Оператор NameOf не оценивается в период выполнения: это константа этапа компиляции; в данном случае константная строка «s». Причина использования NameOf(s) в том, что это предохраняет вас от опечаток. Например, если вы переименовываете параметр метода, то аргумент NameOf будет переименован автоматически. Такого не произойдет в случае простого строкового литерала. Вот еще одна область, где NameOf очень полезен:

Private _age As Integer
Property Age As Integer
  Get
    Return _age
  End Get
  Set
    _age = Value
    RaiseEvent PropertyChanged(
      Me, New PropertyChangedEventArgs(NameOf(Age)))
  End Set
End Property

Заметьте, что NameOf пока отсутствует в Visual Studio 2015 Preview, но появится в финальной версии Visual Studio 2015.

14. Открытый исходный код «Мы пытаемся вовлечь в разработку сообщество. В нем много умных людей. Предложения от сообщества нужны нам не меньше, чем собственные идеи». — Андерс Нейлсберг (Anders Hejlsberg), архитектор C#/Visual Basic

Это улучшение не в самом Visual Basic, а в процессе работы с VB.

Исходный код компилятора VB теперь является открытым. Равно как и процесс проектирования самого языка. Каждое предложение по новой функциональности делается в открытую, под полным контролем сообщества. Члены группы Microsoft Visual Basic Language Design сейчас в основном являются «распорядителями» языка. Группа глубоко анализирует предложения, смотрит, нет ли в нем неожиданных подводных камней или тупиковых ситуаций, и определяет, отвечают ли они заданной планке для включения в язык. Протоколы совещаний группы Language Design публикуются в открытом доступе.

Заключение

В Visual Basic 14 появилась масса усовершенствований. В этой статье было рассказано едва ли о половине из них. Генеральная линия направлена на то, чтобы существующий VB работал эффективнее более простыми для использования способами без введения новых трудных концепций. Более подробную информацию см. на roslyn.codeplex.com и в blogs.msdn.com/vbteam.

Эта статья относится к предварительным версиям Visual Basic 14 и Visual Studio 2015. Любая информация, изложенная в этой статье, может быть изменена.


Лучиан Вишик (Lucian Wischik) — член группы Visual Basic/C# Language Design в Microsoft, отвечает за VB. До перехода в Microsoft работал в академических кругах и занимался теорией параллельной обработки и асинхронностью. Заядлый яхтсмен и пловец на длинные дистанции. С ним можно связаться по адресу lwischik@microsoft.com.

Выражаю благодарность за рецензирование статьи экспертам Microsoft Дастину Кемпбеллу (Dustin Campbell) и Энтони Д. Грину (Anthony D. Green).