C# постоянно развивается. Весной вышла уже седьмая версия. В этой статье будет обзор поддержки последних фич C# в CodeRush for Roslyn. Про C# 7.0 уже было несколько публикаций на хабре, поэтому основное внимание именно на то, как это поддерживается в CodeRush for Roslyn.
Бонусом, в конце статьи, дадим рецепт для тех, кто по каким то причинам не хочет использовать новые языковые фичи.
Task-like возвращаемые типы асинхронных методов
Если раньше асинхронный метод мог возвращать только типы Task или Task<T>, то теперь возможно объявить собственные Task-like типы, которые можно использовать в возвращаемых значениях асинхронных методов.
Во-первых, давайте проверим как работают фичи внутри асинхронного метода, который возвращает Task-like тип. Например, для метода с одним параметром попробуем вызвать Exit Method Contract:
Как видим, CodeRush for Roslyn корректно определил, что return-оператор должен быть пустым и не должен содержать никакого выражения, т.к. в данном случае возвращаемый тип не является универсальным (не содержит параметров типа). Другие фичи, которые генерируют return-операторы также работают корректно. В качестве примера, давайте посмотрим как отработает шаблон "r", который вызывает Smart Return, внутри асинхронного метода:
В этом случае CodeRush правильно распознал, что в return-операторе должно содержаться выражение типа ArgumentKind и вставил соответствующее значение по-умолчанию.
Второй момент — это фичи, которые используют await-выражения с вызовом асинхронного метода, возвращающего Task-like тип. Как видно на следующем скриншоте, CodeRush правильно определяет тип таких await-выражений:
Кортежи значений
Пожалуй, это нововведение в спецификациях языков претендует на роль самого востребованного. Теперь с помощью удобного синтаксиса можно объявлять типы, являющиеся кортежами нескольких значений. Можно задавать как просто типы элементов, так и их имена. Для будущих релизов у нас есть несколько идей по наиболее обширной поддержке кортежей: определять и удалять неиспользуемые пункты, менять пункты местами, использовать кортежи в рефакторинге Convert to Tuple и др. Пока же имеется поддержка кортежей в уже имеющихся фичах. Продемонстрируем это на примере рефакторинга Add Parameter:
Рефакторинг корректно распарсил введённое значение как кортеж из SortingKind и SortingOrder и в качестве дефолтного значения подставил кортеж из дефолтных значений этих типов.
В качестве ещё одного примера продемонстрируем работу фичи Smart Return, которая вызывается раскрытием шаблона r:
Как видим, CodeRush for Roslyn использует имена для переменных кортежа, если они были объявлены.
Вложенные локальные функции
Порой возникает необходимость написания вспомогательной функции использование, которой ограниченно определённым методом. В C# 7 возможно объявить локальную функцию прямо в теле метода. Локальные функции схожи с лямбда-выражениями, но зачастую код использование локальных функций является более наглядным и понятным.
Во-первых, мы обновили фичу Naming Assistant чтобы она работала с локальными функциями:
А еще, уже знакомый Add Parameter тоже теперь работает с новым синтаксисом:
Рефакторинг правильно нашёл декларацию и все ссылки и добавил параметр в нужные позиции.
Расширение использования expression-body и throw-expression
Думаю, что многим пришлось по душе использование expression-body в C# 6, теперь список элементов, где он может быть расширен акцессорами свойств, конструкторами и деструкторами. Рефакторинг Use Expression Body доступен на новых элементах:
Также и обратные данному рефакторингу Expand Method и Expand Accessor доступны, если использован новый синтакс.
Use Expression Body доступен теперь и в тех случаях, когда в теле метода/акcессора отсутствует имплементация и присутствует лишь вызов исключения. С появлением throw-expression запись таких методов можно сделать короче и нагляднее:
Ещё один случай, где throw-expression повышает наглядность кода — это тернарные операторы. Теперь if/else-выражение, в котором в зависимости от условия либо вызывается исключении, либо возвращается/присваивается какое-то значение, можно заменить одним выражение с тернарным оператором. Поможет в этом рефакторинг Compress to Ternary Expression:
Обратный рефакторинг Expand Ternary Expression конечно же также будет доступен на выражениях с throw-expression:
Сопоставление с образцом
Тоже очень мощное нововведение, которое, уверен, уже полюбилось многим пользователям. Оно позволяет в операторах if и case проверить, что переменная является объектом определённого типа и тут же объявить переменную этого типа, избегая лишнего кастинга. В case-операторах в дополнение к этому можно осуществить дополнительные проверки в when-выражении.
В данном разделе мы тоже пока не воплотили все свои идеи. В качестве примера того, что уже имеется, продумонстрируем работу фичи Declare Class на case-выражении, в котором использован новый синтакс:
В данном случае CodeRush for Roslyn корректно определил, что здесь используется шаблон типа, а также сразу задекларировал свойство, используемое в when-выражении. Давайте теперь отладим данный метод при этом включим CodeRush Debug Visualizer:
Когда отладчик доходит до switch-оператора, Debug Visualizer вычисляет выражения во всех case-ветках и отображает какая из них будет выполняться в данном случае, делая код остальных веток более блеклым. Это делает отладку кода более наглядной и удобной, показывая какой код будет выполняться на следующем шаге.
Возврат по ссылке
Теперь ссылка на переменную может использоваться не только в параметре, но и в возращаемом типе метода. Также можно объявлять локальные переменные, которые будут содержать ссылку на переменную.
Возьмём связку из двух уже знакомых нам фич: Smart Return и Declare Method и посмотрим как они отработают в методе, который возвращает значение по ссылке:
Smart Return подставил ключевое слово ref, поскольку return-оператор должен содержать ref-выражение в данном случае. Declare Method, определив, что метод вызывается в ref-выражении, корректно объявил возвращаемый тип как ref int.
Бинарные литералы
Теперь значения каких-то констант в коде можно задавать, используя двоичный код. Это может быть удобным в перечислениях. CodeRush имеет в своём арсенале фичу, которая позволяет ускорить и упростить задачу добавления нового элемента — Smart Duplicate Line. Достаточно нажать Shift + Enter и CodeRush добавит новый элемент, выделив текстовыми полями те элементы, которые потребуют изменений:
И обещанный бонус
Мало кто знает, но на уровне проекта можно выбирать версию языка. CodeRush for Roslyn учитывает опцию Build | Advanced | Language Version.
Например, если поставить C# 4.0, то контекстное меню изменится, потому что интерполяцию строк придумали в C# 6.0.
Но мы не просто скрываем неподдерживаемые пункты меню по условию, мы реализуем полноценную поддержку нужной версии языка на в том числе на уровне генерации кода.
Например, если в проекте стоит версия C# 6.0, то Declare Comparison members из Declare Menu сгенерит код таким образом:
// ...
Class1 other = obj as Class1;
if (other == null) {
throw new ArgumentException(nameof(obj) + " is not a " + nameof(Class1));
}
// ...
А в C# 3.0, например, nameof() еще не было, и код будет таким:
// ...
Class1 other = obj as Class1;
if (other == null) {
throw new ArgumentException("obj is not a Class1");
}
// ...
За счет использования штатных парсеров студии CodeRush for Roslyn одинаково хорошо поддерживает как новые возможности C#, так и старые. CodeRush значительно расширяет возможности Visual Studio не замедляя ее. Особенно это заметно на серьезных enterprise-проектах с большим объемом кода.
Скачать попробовать CodeRush for Roslyn можно на нашем сайте.
Автор: xtraroman