Skip to content

性能反模式

识别和避免源生成器中的性能问题。


📋 文档信息

属性
难度中级
阅读时间25 分钟
前置知识源生成器基础
相关文档反模式索引性能优化

反模式 1: 重复创建编译对象

❌ 错误做法

csharp
public void ProcessNodes(IEnumerable<SyntaxNode> nodes)
{
    foreach (var node in nodes)
    {
        // 每次循环都创建新编译,性能极差
        var compilation = CSharpCompilation.Create("Temp");
        var semanticModel = compilation.GetSemanticModel(node.SyntaxTree);
        // 处理...
    }
}

✅ 正确做法

csharp
private CSharpCompilation _compilation;

public void ProcessNodes(IEnumerable<SyntaxNode> nodes)
{
    // 只创建一次编译
    if (_compilation == null)
    {
        _compilation = CSharpCompilation.Create("Cached");
    }
    
    foreach (var node in nodes)
    {
        var semanticModel = _compilation.GetSemanticModel(node.SyntaxTree);
        // 处理...
    }
}

反模式 2: 不必要的语法树遍历

❌ 错误做法

csharp
public void AnalyzeCode(SyntaxTree tree)
{
    // 多次遍历同一棵树
    var classes = tree.GetRoot().DescendantNodes().OfType<ClassDeclarationSyntax>();
    var methods = tree.GetRoot().DescendantNodes().OfType<MethodDeclarationSyntax>();
    var properties = tree.GetRoot().DescendantNodes().OfType<PropertyDeclarationSyntax>();
}

✅ 正确做法

csharp
public void AnalyzeCode(SyntaxTree tree)
{
    // 一次遍历收集所有需要的节点
    var root = tree.GetRoot();
    var classes = new List<ClassDeclarationSyntax>();
    var methods = new List<MethodDeclarationSyntax>();
    var properties = new List<PropertyDeclarationSyntax>();
    
    foreach (var node in root.DescendantNodes())
    {
        switch (node)
        {
            case ClassDeclarationSyntax cls:
                classes.Add(cls);
                break;
            case MethodDeclarationSyntax method:
                methods.Add(method);
                break;
            case PropertyDeclarationSyntax prop:
                properties.Add(prop);
                break;
        }
    }
}

反模式 3: 缺少缓存

❌ 错误做法

csharp
public string GetTypeName(ITypeSymbol type)
{
    // 每次都重新计算
    return type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
}

✅ 正确做法

csharp
private readonly Dictionary<ITypeSymbol, string> _typeNameCache = new();

public string GetTypeName(ITypeSymbol type)
{
    if (!_typeNameCache.TryGetValue(type, out var name))
    {
        name = type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
        _typeNameCache[type] = name;
    }
    return name;
}

关键要点

  • ✅ 缓存昂贵的对象(编译、语义模型)
  • ✅ 减少语法树遍历次数
  • ✅ 使用缓存存储计算结果
  • ✅ 使用增量生成器提高性能

相关文档


最后更新: 2026-02-06

基于 MIT 许可发布