C# 属性
最后修改时间:2024 年 1 月 31 日
在本文中,我们将展示如何在 C# 中使用属性。
属性是一个成员,它提供了一种灵活的机制来读取、写入或计算私有字段的值。
属性使用访问器,通过访问器可以读取、写入或操作私有字段的值。 属性的读取和写入被转换为 get 和 set 方法调用。 属性在提供方便的字段访问的同时,将数据与外界隔离。
get
属性访问器用于返回属性值,set
属性访问器用于分配新值。 init
属性访问器仅在对象构造期间用于分配新值。 value
关键字用于定义由 set
或 init
访问器分配的值。
属性可以是读写(它们同时具有 get 和 set 访问器)、只读(它们只有 get 访问器)或只写(它们只有 set 访问器)。
带有后备字段的 C# 属性
以下示例使用带有后备字段的属性。
User u = new(); u.Name = "Jane"; Console.WriteLine(u.Name); class User { private string? _name; public string? Name { get { return _name; } set { _name = value; } } }
我们有带有 _name
后备字段的 Name
属性。
User u = new(); u.Name = "Jane"; Console.WriteLine(u.Name);
我们创建一个 User
类的实例。 我们使用字段表示法访问成员字段。
public string? Name { ... }
我们有一个名为 Name
的属性。 它看起来像一个常规的方法声明。 区别在于它具有称为 get
和 set
的特定访问器。
get { return _name; } set { _name = value; }
get
属性访问器用于返回属性值,set
访问器用于分配新值。 value
关键字用于定义由 set 访问器分配的值。
C# 只读属性
要创建只读属性,我们省略 set 访问器,只在实现中提供 get 访问器。
var u = new User("John Doe", "gardener"); Console.WriteLine(u); class User(string name, string occupation) { public string Name { get { return name; } } public string Occupation { get { return occupation; } } public override string ToString() { return $"{name} is a {occupation}"; } }
在该示例中,我们有只读属性。 一旦在构造函数中初始化,它们就无法修改。
public string Name { get { return name; } }
我们通过只提供 get 访问器使属性成为只读。
C# 自动实现的属性
C# 具有自动实现或自动属性。 使用自动属性,编译器会透明地为我们提供后备字段。
var u = new User(); u.Name = "John Doe"; u.Occupation = "gardener"; Console.WriteLine($"{u.Name} is a {u.Occupation}"); class User { public string? Name { get; set; } public string? Occupation { get; set; } }
此代码要短得多。 我们有一个 User
类,其中有两个属性:Name
和 Occupation
。
var u = new User(); u.Name = "John Doe"; u.Occupation = "gardener"; Console.WriteLine($"{u.Name} is a {u.Occupation}");
我们通常像往常一样使用这些属性。
public string? Name { get; set; } public string? Occupation { get; set; }
这里我们有两个自动属性。 没有访问器的实现,也没有成员字段。 编译器将为我们完成剩下的工作。
$ dotnet run John Doe is a gardener
C# init-only 属性
init
关键字用于创建 init-only 属性;这些属性只能在对象构造期间初始化。
var u = new User("John Doe", "gardener"); Console.WriteLine(u); class User(string name, string occupation) { public string Name { get; init; } = name; public string Occupation { get; init; } = occupation; public override string ToString() { return $"{Name} is a {Occupation}"; } }
我们定义两个 init-only 属性;它们在对象构造时初始化。 之后,它们变为不可变的。
class User(string name, string occupation) { ... }
我们使用主构造函数。 它为我们提供了两个参数:name
和 occupation
。 它们稍后用于初始化属性。
public string Name { get; init; } = name; public string Occupation { get; init; } = occupation;
init-only 属性是使用 init
关键字创建的。
C# required 属性
required
关键字用于强制客户端实现该属性。
var u = new User { Name = "John Doe", Occupation = "gardener" }; Console.WriteLine(u); var u2 = new User { Name = "Roger Roe" }; Console.WriteLine(u2); class User { public required string Name { get; init; } public string? Occupation { get; init; } public override string ToString() { return $"User{{ {Name} {Occupation} }}"; } }
我们必须使用对象初始值设定项来创建具有 required
属性的对象。
$ dotnet run User{ John Doe gardener } User{ Roger Roe }
C# 表达式体定义
属性可以使用表达式体定义来简化。 表达式体定义由 =>
符号以及要分配给属性或从属性检索的表达式组成。
var u = new User("John Doe", "gardener"); Console.WriteLine($"{u.Name} is a {u.Occupation}"); class User { private string _name; private string _occupation; public User(string name, string occupation) { Name = name; Occupation = occupation; } public string Name { get => _name; set => _name = value; } public string Occupation { get => _occupation; set => _occupation = value; } }
在该示例中,我们使用表达式体定义来为 User
类定义属性。
$ dotnet run John Doe is a gardener
其他说明
我们可以使用访问修饰符(如 public
、private
或 protected
)标记属性。 属性也可以是 static
、abstract
、virtual
和 sealed
。 它们的用法与常规方法相同。
var bs = new Base(); var dr = new Derived(); Console.WriteLine(bs.Name); Console.WriteLine(dr.Name); class Base { protected string _name = "Base class"; public virtual string Name { set { _name = value; } get { return _name; } } } class Derived : Base { protected new string _name = "Derived class"; public override string Name { set { _name = value; } get { return _name; } } }
在前面的示例中,我们定义了一个虚拟属性,并在 Derived
类中覆盖它。
public virtual string Name { set { _name = value; } get { return _name; } }
Name 属性用 virtual
关键字标记。
protected new string _name = "Derived class";
我们正在隐藏 Derived 类中的成员。 为了抑制编译器警告,我们使用 new
关键字。
public override string Name { set { _name = value; } get { return _name; } }
在这里,我们覆盖了 Base
类的 Name
属性。
来源
在本文中,我们介绍了 C# 属性。
作者
列出所有 C# 教程。