`GenericNameSyntax` в Roslyn представляет синтаксическую модель дженерикового типа, т.е. типа с параметрами типов. Этот класс используется для работы с дженериками, такими как `List<int>` или `Dictionary<string, int>`. Он наследуется от класса `SimpleNameSyntax`, который, в свою очередь, наследуется от `TypeSyntax`. ### Основные свойства `GenericNameSyntax` 1. **`Identifier`** Представляет имя типа без параметров. Это просто имя дженерика, например, `List` в `List<int>` или `Dictionary` в `Dictionary<string, int>`. Пример: ```csharp var genericName = (GenericNameSyntax)typeSyntax; var identifier = genericName.Identifier; // Получает "List" ``` 2. **`TypeArgumentList`** Представляет список аргументов типов, используемых с дженериком. Это `TypeArgumentListSyntax`, который содержит все типы, переданные дженерику в угловых скобках. Пример: ```csharp var arguments = genericName.TypeArgumentList.Arguments; // Получает типы, такие как "int" ``` ### Пример использования `GenericNameSyntax` Допустим, у нас есть код с использованием дженериков, и мы хотим проанализировать его с помощью Roslyn: ```csharp using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using System; using System.Linq; class Program { static void Main() { var code = @" using System.Collections.Generic; public class MyClass { public List<int> myField; public Dictionary<string, int> myDictionary; }"; var tree = CSharpSyntaxTree.ParseText(code); var root = tree.GetRoot(); // Находим все объявления полей var fields = root.DescendantNodes().OfType<FieldDeclarationSyntax>(); foreach (var field in fields) { var variableType = field.Declaration.Type; // Проверяем, является ли тип дженериком if (variableType is GenericNameSyntax genericName) { // Имя дженерика Console.WriteLine(quot;Generic Name: {genericName.Identifier}"); // Аргументы дженерика foreach (var argument in genericName.TypeArgumentList.Arguments) { Console.WriteLine(quot;Type Argument: {argument}"); } } } } } ``` ### Что происходит в этом коде: 1. Мы разбираем исходный код с использованием `CSharpSyntaxTree.ParseText`. 2. Мы находим все поля, используя метод `DescendantNodes()` и фильтруем по типу `FieldDeclarationSyntax`. 3. Для каждого поля мы проверяем, является ли его тип дженериком через проверку на тип `GenericNameSyntax`. 4. Если это дженерик, выводим имя дженерика и его аргументы типов. Вывод программы для кода будет таким: ``` Generic Name: List Type Argument: int Generic Name: Dictionary Type Argument: string Type Argument: int ``` ### Полезные методы `GenericNameSyntax` 1. **`WithIdentifier`** Позволяет изменить идентификатор (имя) дженерика. Это полезно, если вам нужно изменить имя дженерика в синтаксическом дереве. Пример: ```csharp var newGenericName = genericName.WithIdentifier(SyntaxFactory.Identifier("NewName")); ``` 2. **`WithTypeArgumentList`** Позволяет заменить список аргументов типов. Это может быть полезно при замене параметров типов на другие. Пример: ```csharp var newArguments = SyntaxFactory.TypeArgumentList(SyntaxFactory.SingletonSeparatedList<TypeSyntax>( SyntaxFactory.ParseTypeName("double"))); var newGenericName = genericName.WithTypeArgumentList(newArguments); ``` ### Использование `GenericNameSyntax` в синтаксическом анализе `GenericNameSyntax` — это важный элемент при анализе кода, где используются дженерики. С его помощью можно: - Извлекать имя дженерика и его параметры. - Изменять параметры дженерика в ходе анализа или трансформации кода. - Выполнять сравнение и проверки типов на использование дженериков. Это делает его полезным для построения статического анализа кода, работы с типами и написания кодогенерации в проектах, использующих Roslyn.