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# 教程。