You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Roslyn获取当前项目C#语言版本,优化空参数校验重构

我最近在用Roslyn开发一个自动添加ArgumentNullException的简单重构工具,正好碰到了需要根据项目C#版本适配不同写法的问题,这里把思路和解决方法整理出来:

需求背景

这个工具的核心功能是自动为方法参数生成null检查代码,但不同C#版本的最优写法差异很大:

  • C# 6之前:只能用硬编码字符串传递参数名,可读性和安全性都一般:
if (parameter == null) throw new ArgumentNullException("parameter");
_parameter = parameter;
  • C# 6+:可以用nameof运算符,既保留可读性又实现类型安全:
if (parameter == null) throw new ArgumentNullException(nameof(parameter));
_parameter = parameter;
  • C# 7+:借助throw表达式能把代码简化成一行,更加简洁:
_parameter = parameter ?? throw new ArgumentNullException(nameof(parameter));

要让工具自动适配这些写法,关键就是通过Roslyn获取当前项目的C#语言版本。

获取C#版本的具体实现

在Roslyn的分析器或代码修复提供者中,我们可以通过Compilation对象轻松拿到版本信息:

  1. 首先从分析上下文(比如SyntaxNodeAnalysisContext)或代码修复上下文(CodeFixContext)中获取Compilation实例;
  2. 访问Compilation.LanguageVersion属性,它会返回一个LanguageVersion枚举值,对应项目的C#版本。

举个实际的代码示例:

public override void Initialize(AnalysisContext context)
{
    context.RegisterSyntaxNodeAction(AnalyzeParameterAssignment, SyntaxKind.AssignmentExpression);
}

private void AnalyzeParameterAssignment(SyntaxNodeAnalysisContext context)
{
    // 获取当前项目的编译信息
    var compilation = context.Compilation;
    var csharpVersion = compilation.LanguageVersion;

    // 根据版本选择对应的代码生成逻辑
    if (csharpVersion >= LanguageVersion.CSharp7)
    {
        // 生成C#7+的throw表达式写法
        GenerateThrowExpressionNullCheck(context);
    }
    else if (csharpVersion >= LanguageVersion.CSharp6)
    {
        // 生成C#6+带nameof的写法
        GenerateNameofNullCheck(context);
    }
    else
    {
        // 生成传统硬编码字符串的写法
        GenerateLegacyNullCheck(context);
    }
}

额外注意点

  • LanguageVersion枚举覆盖了从C# 1到最新正式/预览版本的所有取值,比如CSharp8、CSharp10、Preview等,能满足绝大多数场景的判断;
  • 如果项目设置了latest版本,LanguageVersion会自动映射到当前Roslyn支持的最新正式版本,无需额外处理。

内容的提问来源于stack exchange,提问作者Akos Nagy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 11:05:49