Pull to refresh

О поддержке языковых фич C# в Visual Studio и в CodeRush for Roslyn

Reading time5 min
Views7.1K

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 SyntaxNode.


Бинарные литералы


Теперь значения каких-то констант в коде можно задавать, используя двоичный код. Это может быть удобным в перечислениях. 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 можно на нашем сайте.

Tags:
Hubs:
+17
Comments6

Articles

Change theme settings

Information

Website
www.developersoft.ru
Registered
Founded
1998
Employees
201–500 employees
Location
Россия