C# 14的field关键字怎么使用?属性访问器新写法完整示例
2026-10-03 12 0
C# 14 引入了一个很实用的属性语法:field 关键字。它允许开发者在 get、set 或 init 访问器中直接访问属性对应的编译器生成后备字段,不需要再单独声明 _name、_value 这类私有字段。
这个功能已经随 .NET 10 正式发布。
field关键字是什么?
以前写一个带简单校验的属性,通常需要声明后备字段:
private string _name = string.Empty;
public string Name
{
get => _name;
set => _name = value.Trim();
}
C# 14 可以直接写成:
public string Name
{
get;
set => field = value.Trim();
}
这里的 field 就代表该属性对应的编译器生成后备字段。get; 保留自动访问器,set 则加入自己的处理逻辑。
这种写法可以减少大量重复代码,同时保留属性访问器的控制能力。
最常见的属性校验
例如用户名不能为 null,可以直接在 set 中处理:
public class User
{
public string Name
{
get;
set => field = value ?? throw new ArgumentNullException(nameof(value));
}
}
使用时:
var user = new User
{
Name = "Tom"
};
Console.WriteLine(user.Name);
如果传入 null,setter 会抛出异常。
相比传统 _name 字段方案,属性本身已经包含了存储和赋值逻辑,代码更加紧凑。
get和set可以混合使用
C# 14 的一个重要变化,是属性可以混合使用自动访问器和带方法体的访问器。
例如:
public int Age
{
get;
set
{
if (value < 0 || value > 150)
throw new ArgumentOutOfRangeException(nameof(value));
field = value;
}
}
这里 get; 自动读取后备字段,set 负责检查输入范围。
也可以使用表达式主体:
public int Age
{
get;
set => field = Math.Clamp(value, 0, 150);
}
这样就不需要额外声明 _age。
使用field实现数据规范化
field 很适合处理字符串:
public string Email
{
get;
set => field = value?.Trim().ToLowerInvariant() ?? string.Empty;
}
调用:
user.Email = " TEST@EXAMPLE.COM ";
Console.WriteLine(user.Email);
最终保存的值会变成test@example.com。这类场景过去通常需要一个私有字段配合完整的 get、set 访问器,现在可以直接写在属性内部。
field实现延迟初始化
field 也可以用于懒加载:
public DatabaseConnection Connection
{
get => field ??= CreateConnection();
}
private DatabaseConnection CreateConnection()
{
return new DatabaseConnection();
}
第一次访问 Connection 时创建对象,后续访问直接返回已经保存的实例。
微软官方文档也将 field ??= 列为 C# 14 中典型的懒初始化用法。
init访问器也可以使用field
如果属性只能在对象初始化阶段赋值,可以配合 init:
public class Product
{
public string Name
{
get;
init => field = value?.Trim()
?? throw new ArgumentNullException(nameof(value));
}
public decimal Price
{
get;
init
{
if (value < 0)
throw new ArgumentOutOfRangeException(nameof(value));
field = value;
}
}
}
创建对象:
var product = new Product
{
Name = " C# 14 ",
Price = 99
};
Console.WriteLine(product.Name);
对象初始化完成后,init 属性不能再通过普通赋值修改。
属性通知也能直接操作field
在需要触发属性变化通知的场景中,也可以直接使用 field:
public string Name
{
get;
set
{
if (field == value)
return;
field = value;
OnPropertyChanged(nameof(Name));
}
}
完整示例:
public class User : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
public string Name
{
get;
set
{
if (field == value)
return;
field = value;
OnPropertyChanged(nameof(Name));
}
}
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(
this,
new PropertyChangedEventArgs(propertyName));
}
}
这里没有 _name 字段,属性依然拥有自己的编译器生成存储空间。
field和普通字段有什么区别?
field 不是一个需要自己声明的变量,也不能在类中单独使用:
field = "test"; // 错误
它只在相关属性的访问器上下文中代表该属性的后备字段。
另外,C# 14 中 field 属于上下文关键字。如果项目以前存在名为 field 的变量,在升级到 C# 14 后可能产生歧义。官方建议使用 @field 或 this.field 处理相关标识符冲突。
项目需要什么版本?
field 是 C# 14 的语言功能,正式版本随 .NET 10 发布。如果项目使用 .NET 10 SDK,可以直接使用 C# 14。对于旧项目,除了检查目标框架,还需要确认项目实际使用的 C# 语言版本。
总结
C# 14 的 field 主要解决一个很常见的问题:属性只有一点额外逻辑时,不想为了它专门创建一个私有后备字段。
最常见的写法就是:
public string Name
{
get;
set => field = value.Trim();
}
需要校验时可以写 set 方法体,需要懒加载时可以使用 field ??=,需要初始化阶段校验则可以配合 init。对于原本大量使用 _xxx 后备字段的代码,C# 14 的这种属性写法可以明显减少模板代码,同时保持属性本身的可读性。