在日常 C# 开发中,我们经常需要获取变量名、属性名、方法名或类型名的字符串形式,比如:
- 抛出参数异常时提示参数名
- 日志记录字段名称
- 数据绑定、反射、序列化
- MVVM / ASP.NET 中的属性通知
在 C# 6.0 之前,这些字符串往往是硬编码的魔法字符串(Magic String),维护成本极高。而 nameof 的出现,几乎是一次“工程级”的体验升级。
什么是 nameof
nameof 是 C# 6.0 引入的一个编译期运算符,用于在编译时获取一个符号(变量、属性、方法、类型等)的名称字符串。
1
2
|
int count = 10;
Console.WriteLine(nameof(count)); // count
|
核心特性:
- 编译时解析
- 零运行时开销
- 重构安全(重命名不会出 Bug)
为什么要用 nameof
先看一个例子:
1
2
3
4
5
6
7
|
void SetAge(int age)
{
if (age < 0)
{
throw new ArgumentOutOfRangeException("Age cannot be negative.", "age");
}
}
|
如果某天把参数age改成userAge:
1
|
void SetAge(int userAge)
|
那么问题来了:
- 编译不会报错
- 异常参数名仍然是字符串
age
- IDE 重构也没有用
但如果使用nameof的话:
1
2
3
4
5
6
7
|
void SetAge(int userAge)
{
if (userAge < 0)
{
throw new ArgumentOutOfRangeException("Age cannot be negative.", nameof(userAge));
}
}
|
优点立刻显现:
nameof 的常见用法
参数校验
1
2
3
4
|
public void Login(string username) {
if (username == null)
throw new ArgumentNullException(nameof(username));
}
|
这是.NET 官方源码中最常见的 nameof 使用场景。
获取属性名
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public class User: INotifyPropertyChanged
{
private string _name;
public string Name {
get => _name;
set
{
_name = value;
OnPropertyChanged(nameof(Name));
}
}
}
|
相比:
1
|
OnPropertyChanged("Name");
|
nameof更安全、更优雅。
日志 & 诊断信息
1
|
_logger.Debug("Current value of {Field}", nameof(order,TotalPrice));
|
避免字段名写错、重构友好。
获取类型名
1
2
|
Console.WriteLine(nameof(List<int>)); // List
Console.WriteLine(nameof(UserService)); // UserService
|
nameof(List<int>)返回的是类型名,不包含泛型参数。
方法名 / 事件名
1
2
|
Console.WriteLine(nameof(DoWork));
Console.WriteLine(nameof(PropertyChanged));
|
适用于 AOP、日志以及诊断追踪。
nameof 的一些注意点
nameof 不会求值
1
2
|
int count = 10;
Console.WriteLine(nameof(count + 1)); // 编译错误
|
nameof只接受符号,不接受表达式。
支持命名空间 & 成员访问
1
2
|
Console.WriteLine(nameof(System.Text.StringBuilder)); // StringBuilder
Console.WriteLine(nameof(user.Name)); // Name
|
只返回最后一个标识符。
推荐