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);
}
More
目前该特性的支持已经完成并合并入主分支,预计下个版本的 SDK 发布我们就可以使用了~~
References
https://github.com/dotnet/csharplang/blob/main/proposals/extended-nameof-scope.md
https://sharplab.io/#v2:EYLgtghglgdgNAExAagD4AEBMBGAsAKHQAYACdbAOgGEB7MABxpgFMYAXAWRoWYBsBuAsTKUASgFd2UMM2p16UXswBOAZRUA3KAGNmAZ0H4hAZjKYSVEgG8CJOyQDaAEX3blUemyhMAFABIAIisYCBkaADMfEJkAUQAPemV9PW8YAEoAXxIAST0AOXFeXgB5ZRiGNgBPALSAXVt7dFNgGhpeEg4fclJo5jhHKggilQBBZQBzcRl2eMTk1KjQ5gjFmTS67pJe2aS9FKYSAF4twt40kga7G3x7W7IAdhEiClyCotLyz0rV5jTDW4yBAyQA