Skip to content

符号类型详解

📚 文档导航

本文档详细介绍各种符号类型及其使用方法。

📖 文档系列

文档内容难度
符号系统基础基础概念、符号层次、快速入门🟢 入门
符号类型详解INamedTypeSymbol、IMethodSymbol、IPropertySymbol 等🟡 中级
符号操作获取、遍历、查询、比较符号🟡 中级
高级主题继承、接口、特性、显示格式、文档注释🔴 高级
最佳实践性能优化、实战场景、设计模式🟡 中级

符号类型关系图


INamedTypeSymbol 详解

INamedTypeSymbol 表示命名类型:类、结构、接口、枚举、委托。

基本属性

csharp
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

public class NamedTypeSymbolExamples
{
    public void DemonstrateNamedTypeSymbol()
    {
        var code = @"
            namespace MyApp
            {
                public abstract class Animal
                {
                    public string Name { get; set; }
                    public abstract void MakeSound();
                }
                
                public class Dog : Animal
                {
                    public override void MakeSound()
                    {
                        Console.WriteLine(""Woof!"");
                    }
                }
            }
        ";
        
        var tree = CSharpSyntaxTree.ParseText(code);
        var compilation = CreateCompilation(tree);
        var model = compilation.GetSemanticModel(tree);
        var root = tree.GetRoot();
        
        var dogClass = root.DescendantNodes()
            .OfType<ClassDeclarationSyntax>()
            .First(c => c.Identifier.Text == "Dog");
        
        var typeSymbol = model.GetDeclaredSymbol(dogClass) as INamedTypeSymbol;
        
        // 基本信息
        Console.WriteLine($"名称: {typeSymbol.Name}");
        Console.WriteLine($"完整名称: {typeSymbol.ToDisplayString()}");
        Console.WriteLine($"元数据名称: {typeSymbol.MetadataName}");
        
        // 类型种类
        Console.WriteLine($"类型种类: {typeSymbol.TypeKind}");
        // 输出: TypeKind.Class
        
        // 访问修饰符
        Console.WriteLine($"访问级别: {typeSymbol.DeclaredAccessibility}");
        // 输出: Accessibility.Public
        
        // 修饰符
        Console.WriteLine($"是抽象: {typeSymbol.IsAbstract}");
        Console.WriteLine($"是密封: {typeSymbol.IsSealed}");
        Console.WriteLine($"是静态: {typeSymbol.IsStatic}");
        Console.WriteLine($"是值类型: {typeSymbol.IsValueType}");
        Console.WriteLine($"是引用类型: {typeSymbol.IsReferenceType}");
        
        // 继承关系
        Console.WriteLine($"基类: {typeSymbol.BaseType?.ToDisplayString()}");
        // 输出: MyApp.Animal
        
        Console.WriteLine($"接口:");
        foreach (var iface in typeSymbol.Interfaces)
        {
            Console.WriteLine($"  - {iface.ToDisplayString()}");
        }
        
        // 成员
        Console.WriteLine($"成员数量: {typeSymbol.GetMembers().Length}");
        Console.WriteLine($"方法数量: {typeSymbol.GetMembers().OfType<IMethodSymbol>().Count()}");
        Console.WriteLine($"属性数量: {typeSymbol.GetMembers().OfType<IPropertySymbol>().Count()}");
    }
    
    private Compilation CreateCompilation(SyntaxTree tree)
    {
        return CSharpCompilation.Create("temp")
            .AddReferences(
                MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
                MetadataReference.CreateFromFile(typeof(Console).Assembly.Location)
            )
            .AddSyntaxTrees(tree);
    }
}

泛型类型

csharp
public class GenericTypeExamples
{
    public void AnalyzeGenericType()
    {
        var code = @"
            public class Container<T> where T : class
            {
                public T Value { get; set; }
            }
            
            public class Usage
            {
                public void Test()
                {
                    var container = new Container<string>();
                }
            }
        ";
        
        var tree = CSharpSyntaxTree.ParseText(code);
        var compilation = CreateCompilation(tree);
        var model = compilation.GetSemanticModel(tree);
        var root = tree.GetRoot();
        
        // 分析泛型类定义
        var containerClass = root.DescendantNodes()
            .OfType<ClassDeclarationSyntax>()
            .First(c => c.Identifier.Text == "Container");
        
        var typeSymbol = model.GetDeclaredSymbol(containerClass) as INamedTypeSymbol;
        
        Console.WriteLine($"是泛型: {typeSymbol.IsGenericType}");
        Console.WriteLine($"类型参数数量: {typeSymbol.TypeParameters.Length}");
        
        foreach (var typeParam in typeSymbol.TypeParameters)
        {
            Console.WriteLine($"类型参数: {typeParam.Name}");
            Console.WriteLine($"  有引用类型约束: {typeParam.HasReferenceTypeConstraint}");
            Console.WriteLine($"  有值类型约束: {typeParam.HasValueTypeConstraint}");
            Console.WriteLine($"  有构造函数约束: {typeParam.HasConstructorConstraint}");
        }
        
        // 分析泛型类型使用
        var objectCreation = root.DescendantNodes()
            .OfType<ObjectCreationExpressionSyntax>()
            .First();
        
        var createdType = model.GetTypeInfo(objectCreation).Type as INamedTypeSymbol;
        
        Console.WriteLine($"\n构造的泛型类型: {createdType.ToDisplayString()}");
        Console.WriteLine($"原始定义: {createdType.OriginalDefinition.ToDisplayString()}");
        Console.WriteLine($"类型参数:");
        foreach (var typeArg in createdType.TypeArguments)
        {
            Console.WriteLine($"  - {typeArg.ToDisplayString()}");
        }
    }
    
    private Compilation CreateCompilation(SyntaxTree tree)
    {
        return CSharpCompilation.Create("temp")
            .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location))
            .AddSyntaxTrees(tree);
    }
}

IMethodSymbol 详解

IMethodSymbol 表示方法、构造函数、析构函数等。

基本属性

csharp
public class MethodSymbolExamples
{
    public void DemonstrateMethodSymbol()
    {
        var code = @"
            public class Calculator
            {
                public async Task<int> AddAsync(int a, int b)
                {
                    await Task.Delay(100);
                    return a + b;
                }
                
                public static void Log(string message)
                {
                    Console.WriteLine(message);
                }
                
                public virtual void Process() { }
            }
        ";
        
        var tree = CSharpSyntaxTree.ParseText(code);
        var compilation = CreateCompilation(tree);
        var model = compilation.GetSemanticModel(tree);
        var root = tree.GetRoot();
        
        var addMethod = root.DescendantNodes()
            .OfType<MethodDeclarationSyntax>()
            .First(m => m.Identifier.Text == "AddAsync");
        
        var methodSymbol = model.GetDeclaredSymbol(addMethod) as IMethodSymbol;
        
        // 基本信息
        Console.WriteLine($"方法名: {methodSymbol.Name}");
        Console.WriteLine($"完整签名: {methodSymbol.ToDisplayString()}");
        
        // 返回类型
        Console.WriteLine($"返回类型: {methodSymbol.ReturnType.ToDisplayString()}");
        
        // 参数
        Console.WriteLine($"参数数量: {methodSymbol.Parameters.Length}");
        foreach (var param in methodSymbol.Parameters)
        {
            Console.WriteLine($"  - {param.Type.ToDisplayString()} {param.Name}");
        }
        
        // 修饰符
        Console.WriteLine($"是异步: {methodSymbol.IsAsync}");
        Console.WriteLine($"是静态: {methodSymbol.IsStatic}");
        Console.WriteLine($"是虚方法: {methodSymbol.IsVirtual}");
        Console.WriteLine($"是重写: {methodSymbol.IsOverride}");
        Console.WriteLine($"是抽象: {methodSymbol.IsAbstract}");
        Console.WriteLine($"是密封: {methodSymbol.IsSealed}");
        Console.WriteLine($"是扩展方法: {methodSymbol.IsExtensionMethod}");
        
        // 方法种类
        Console.WriteLine($"方法种类: {methodSymbol.MethodKind}");
        // MethodKind.Ordinary, Constructor, Destructor, etc.
    }
    
    private Compilation CreateCompilation(SyntaxTree tree)
    {
        return CSharpCompilation.Create("temp")
            .AddReferences(
                MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
                MetadataReference.CreateFromFile(typeof(Console).Assembly.Location),
                MetadataReference.CreateFromFile(typeof(Task).Assembly.Location)
            )
            .AddSyntaxTrees(tree);
    }
}

泛型方法

csharp
public class GenericMethodExamples
{
    public void AnalyzeGenericMethod()
    {
        var code = @"
            public class Utils
            {
                public T Clone<T>(T source) where T : ICloneable
                {
                    return (T)source.Clone();
                }
            }
        ";
        
        var tree = CSharpSyntaxTree.ParseText(code);
        var compilation = CreateCompilation(tree);
        var model = compilation.GetSemanticModel(tree);
        var root = tree.GetRoot();
        
        var method = root.DescendantNodes()
            .OfType<MethodDeclarationSyntax>()
            .First();
        
        var methodSymbol = model.GetDeclaredSymbol(method) as IMethodSymbol;
        
        Console.WriteLine($"是泛型方法: {methodSymbol.IsGenericMethod}");
        Console.WriteLine($"类型参数数量: {methodSymbol.TypeParameters.Length}");
        
        foreach (var typeParam in methodSymbol.TypeParameters)
        {
            Console.WriteLine($"类型参数: {typeParam.Name}");
            Console.WriteLine($"  约束:");
            foreach (var constraint in typeParam.ConstraintTypes)
            {
                Console.WriteLine($"    - {constraint.ToDisplayString()}");
            }
        }
    }
    
    private Compilation CreateCompilation(SyntaxTree tree)
    {
        return CSharpCompilation.Create("temp")
            .AddReferences(
                MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
                MetadataReference.CreateFromFile(typeof(ICloneable).Assembly.Location)
            )
            .AddSyntaxTrees(tree);
    }
}

IPropertySymbol 详解

IPropertySymbol 表示属性和索引器。

基本属性

csharp
public class PropertySymbolExamples
{
    public void DemonstratePropertySymbol()
    {
        var code = @"
            public class Person
            {
                // 自动属性
                public string Name { get; set; }
                
                // 只读属性
                public int Age { get; }
                
                // 带逻辑的属性
                private string _email;
                public string Email
                {
                    get => _email;
                    set => _email = value?.ToLower();
                }
                
                // 表达式体属性
                public string FullInfo => $""{Name}, {Age}"";
                
                // 索引器
                public string this[int index]
                {
                    get => index.ToString();
                    set { }
                }
            }
        ";
        
        var tree = CSharpSyntaxTree.ParseText(code);
        var compilation = CreateCompilation(tree);
        var model = compilation.GetSemanticModel(tree);
        var root = tree.GetRoot();
        
        var classDecl = root.DescendantNodes()
            .OfType<ClassDeclarationSyntax>()
            .First();
        
        var typeSymbol = model.GetDeclaredSymbol(classDecl) as INamedTypeSymbol;
        
        foreach (var property in typeSymbol.GetMembers().OfType<IPropertySymbol>())
        {
            Console.WriteLine($"属性: {property.Name}");
            Console.WriteLine($"  类型: {property.Type.ToDisplayString()}");
            Console.WriteLine($"  访问级别: {property.DeclaredAccessibility}");
            
            // 访问器
            Console.WriteLine($"  有 getter: {property.GetMethod != null}");
            Console.WriteLine($"  有 setter: {property.SetMethod != null}");
            
            if (property.GetMethod != null)
            {
                Console.WriteLine($"  getter 访问级别: {property.GetMethod.DeclaredAccessibility}");
            }
            
            if (property.SetMethod != null)
            {
                Console.WriteLine($"  setter 访问级别: {property.SetMethod.DeclaredAccessibility}");
            }
            
            // 特殊属性
            Console.WriteLine($"  是索引器: {property.IsIndexer}");
            Console.WriteLine($"  是只读: {property.IsReadOnly}");
            Console.WriteLine($"  是只写: {property.IsWriteOnly}");
            Console.WriteLine($"  是静态: {property.IsStatic}");
            Console.WriteLine($"  是虚属性: {property.IsVirtual}");
            Console.WriteLine($"  是重写: {property.IsOverride}");
            Console.WriteLine();
        }
    }
    
    private Compilation CreateCompilation(SyntaxTree tree)
    {
        return CSharpCompilation.Create("temp")
            .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location))
            .AddSyntaxTrees(tree);
    }
}

IFieldSymbol 详解

IFieldSymbol 表示字段。

基本属性

csharp
public class FieldSymbolExamples
{
    public void DemonstrateFieldSymbol()
    {
        var code = @"
            public class Constants
            {
                public const int MaxValue = 100;
                public static readonly string AppName = ""MyApp"";
                private int _count;
                public readonly DateTime CreatedAt;
            }
        ";
        
        var tree = CSharpSyntaxTree.ParseText(code);
        var compilation = CreateCompilation(tree);
        var model = compilation.GetSemanticModel(tree);
        var root = tree.GetRoot();
        
        var classDecl = root.DescendantNodes()
            .OfType<ClassDeclarationSyntax>()
            .First();
        
        var typeSymbol = model.GetDeclaredSymbol(classDecl) as INamedTypeSymbol;
        
        foreach (var field in typeSymbol.GetMembers().OfType<IFieldSymbol>())
        {
            Console.WriteLine($"字段: {field.Name}");
            Console.WriteLine($"  类型: {field.Type.ToDisplayString()}");
            Console.WriteLine($"  访问级别: {field.DeclaredAccessibility}");
            Console.WriteLine($"  是常量: {field.IsConst}");
            Console.WriteLine($"  是只读: {field.IsReadOnly}");
            Console.WriteLine($"  是静态: {field.IsStatic}");
            Console.WriteLine($"  是 volatile: {field.IsVolatile}");
            
            if (field.IsConst && field.HasConstantValue)
            {
                Console.WriteLine($"  常量值: {field.ConstantValue}");
            }
            
            Console.WriteLine();
        }
    }
    
    private Compilation CreateCompilation(SyntaxTree tree)
    {
        return CSharpCompilation.Create("temp")
            .AddReferences(
                MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
                MetadataReference.CreateFromFile(typeof(DateTime).Assembly.Location)
            )
            .AddSyntaxTrees(tree);
    }
}

IParameterSymbol 详解

IParameterSymbol 表示方法参数。

基本属性

csharp
public class ParameterSymbolExamples
{
    public void DemonstrateParameterSymbol()
    {
        var code = @"
            public class Example
            {
                public void Method(
                    int required,
                    string optional = ""default"",
                    params int[] numbers)
                {
                }
                
                public void RefMethod(
                    ref int refParam,
                    out int outParam,
                    in int inParam)
                {
                    outParam = 0;
                }
            }
        ";
        
        var tree = CSharpSyntaxTree.ParseText(code);
        var compilation = CreateCompilation(tree);
        var model = compilation.GetSemanticModel(tree);
        var root = tree.GetRoot();
        
        var methods = root.DescendantNodes()
            .OfType<MethodDeclarationSyntax>();
        
        foreach (var method in methods)
        {
            var methodSymbol = model.GetDeclaredSymbol(method) as IMethodSymbol;
            
            Console.WriteLine($"方法: {methodSymbol.Name}");
            
            foreach (var param in methodSymbol.Parameters)
            {
                Console.WriteLine($"  参数: {param.Name}");
                Console.WriteLine($"    类型: {param.Type.ToDisplayString()}");
                Console.WriteLine($"    位置: {param.Ordinal}");
                Console.WriteLine($"    是可选: {param.IsOptional}");
                Console.WriteLine($"    是 params: {param.IsParams}");
                Console.WriteLine($"    是 this: {param.IsThis}");
                
                // 引用类型
                switch (param.RefKind)
                {
                    case RefKind.None:
                        Console.WriteLine($"    传递方式: 值传递");
                        break;
                    case RefKind.Ref:
                        Console.WriteLine($"    传递方式: ref");
                        break;
                    case RefKind.Out:
                        Console.WriteLine($"    传递方式: out");
                        break;
                    case RefKind.In:
                        Console.WriteLine($"    传递方式: in");
                        break;
                }
                
                // 默认值
                if (param.HasExplicitDefaultValue)
                {
                    Console.WriteLine($"    默认值: {param.ExplicitDefaultValue ?? "null"}");
                }
                
                Console.WriteLine();
            }
        }
    }
    
    private Compilation CreateCompilation(SyntaxTree tree)
    {
        return CSharpCompilation.Create("temp")
            .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location))
            .AddSyntaxTrees(tree);
    }
}

INamespaceSymbol 详解

INamespaceSymbol 表示命名空间。

基本属性

csharp
public class NamespaceSymbolExamples
{
    public void DemonstrateNamespaceSymbol(Compilation compilation)
    {
        // 获取全局命名空间
        var globalNamespace = compilation.GlobalNamespace;
        
        Console.WriteLine("全局命名空间成员:");
        ExploreNamespace(globalNamespace, 0);
    }
    
    private void ExploreNamespace(INamespaceSymbol ns, int depth)
    {
        var indent = new string(' ', depth * 2);
        
        // 获取子命名空间
        foreach (var childNs in ns.GetNamespaceMembers())
        {
            Console.WriteLine($"{indent}命名空间: {childNs.Name}");
            Console.WriteLine($"{indent}  完整名称: {childNs.ToDisplayString()}");
            Console.WriteLine($"{indent}  是全局: {childNs.IsGlobalNamespace}");
            
            ExploreNamespace(childNs, depth + 1);
        }
        
        // 获取类型成员
        foreach (var type in ns.GetTypeMembers())
        {
            Console.WriteLine($"{indent}类型: {type.Name} ({type.TypeKind})");
        }
    }
}

ILocalSymbol 详解

ILocalSymbol 表示局部变量。

基本属性

csharp
public class LocalSymbolExamples
{
    public void DemonstrateLocalSymbol()
    {
        var code = @"
            public class Example
            {
                public void Method()
                {
                    const int maxValue = 100;
                    var name = ""John"";
                    ref int refValue = ref GetValue();
                }
                
                private ref int GetValue() => ref _value;
                private int _value;
            }
        ";
        
        var tree = CSharpSyntaxTree.ParseText(code);
        var compilation = CreateCompilation(tree);
        var model = compilation.GetSemanticModel(tree);
        var root = tree.GetRoot();
        
        var method = root.DescendantNodes()
            .OfType<MethodDeclarationSyntax>()
            .First(m => m.Identifier.Text == "Method");
        
        var locals = method.DescendantNodes()
            .OfType<VariableDeclaratorSyntax>()
            .Select(v => model.GetDeclaredSymbol(v) as ILocalSymbol)
            .Where(l => l != null);
        
        foreach (var local in locals)
        {
            Console.WriteLine($"局部变量: {local.Name}");
            Console.WriteLine($"  类型: {local.Type.ToDisplayString()}");
            Console.WriteLine($"  是常量: {local.IsConst}");
            Console.WriteLine($"  是 ref: {local.IsRef}");
            Console.WriteLine($"  是 ref readonly: {local.IsRefReadOnly}");
            
            if (local.IsConst && local.HasConstantValue)
            {
                Console.WriteLine($"  常量值: {local.ConstantValue}");
            }
            
            Console.WriteLine();
        }
    }
    
    private Compilation CreateCompilation(SyntaxTree tree)
    {
        return CSharpCompilation.Create("temp")
            .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location))
            .AddSyntaxTrees(tree);
    }
}

下一步


🔗 相关资源


最后更新: 2025-01-21

基于 MIT 许可发布