C# 11更加实用的 nameof

Intro

从 C# 6.0 开始,我们可以开始使用 nameof 来引用参数名称,在可能使用 nameof 的地方,一般都推荐使用以便于重构时的自动更新,在之前的 C# 版本中,如果想要在方法参数中或者方法 attribute 中通过 nameof 来引用方法会编译报错,从 C# 11 开始,扩展了 nameof 的作用域,我们就可以使用了,下面看几个示例.

Samples

Method parameter reference

在 .NET 6 中引入了一个新的调用者信息 Attribute CallerArgumentExpression , 使用它我们可以简化很多日志或者 metrics 记录等场景,自动获取调用的信息,但是美中不足的是,我们需要使用字符串来引用方法参数,如下所示:

public static ICollection<T> NotEmpty<T>([NotNull] ICollection<T> collection, [CallerArgumentExpression("collection")] string? paramName = null)
{
    if (collection.Count == 0)
    {
        throw new ArgumentException("The collection could not be empty", paramName);
    }
    return collection;
}

如这样的例子,我们引用 collection 参数只能使用字符串,这对于我们对 collection 参数名进行重构的时候,就会仍然需要手动修改 CallerArgumentExpression 中的参数名,在新版本中,我们将可以直接使用 nameof(collection) 来代替字符串,如下:

public static ICollection<T> NotEmpty<T>([NotNull] ICollection<T> collection, [CallerArgumentExpression(nameof(collection))] string? paramName = null)
{
    NotNull(collection, paramName);
    if (collection.Count == 0)
    {
        throw new ArgumentException("The collection could not be empty", paramName);
    }
    return collection;
}

这样就不容易出现一时手误参数名称输入错误,而且 nameof 能够提供更好的重构体验

Attribute reference

除了方法参数中引用方法参数,我们还可以使用方法的 Attribute 中引用方法参数,示例如下:

[Description(nameof(nameExpression))]
public bool M(string name, [CallerArgumentExpression(nameof(name))]string nameExpression = null) 
{
    return string.IsNullOrEmpty(name);
}

得益于 C# 中的常量插值字符串特性,我们也是可以在 Attribute 中使用常量插值字符串的,如下:

[Description($"{nameof(nameExpression)} IsNullOrEmpty")]
public bool M(string name, [CallerArgumentExpression(nameof(name))]string nameExpression = null) 
{
    return string.IsNullOrEmpty(name);
}

 

C# 11更加实用的 nameof

More

目前该特性的支持已经完成并合并入主分支,预计下个版本的 SDK 发布我们就可以使用了~~