C#属性教程展示了如何在C#中使用属性。
属性是一个成员,它提供了一种灵活的机制来读取、写入或计算私有字段的值。
属性使用访问器,通过访问器可以读取、写入或操作私有字段的值。属性读取和写入被转换为get和set方法调用。属性保护数据不受外界影响,同时具有方便的现场访问。
get
属性访问器用于返回属性值,set
属性访问器用于分配新值。init
属性访问器仅在对象构造期间用于分配新值。value
关键字用于定义由set
或init
访问器分配的值。
属性可以是读写的(它们同时具有get和set访问器)、只读的(它们只有get访问器)或只写的(它们只有setaccessor)。
带有支持字段的C#属性
以下示例使用带有支持字段的属性。
var u = new User(); u.Name = "Jane"; Console.WriteLine(u.Name); class User { private string _name; public string Name { get { return _name; } set { _name = value; } } }
我们有Name
属性和_name
backingfield。
var u = new User(); u.Name = "Jane"; Console.WriteLine(u.Name);
我们创建了一个User
类的实例。我们使用字段表示法访问成员字段。
public string Name { ... }
我们有一个名为Name
的属性。它看起来像一个常规方法声明。不同之处在于它有特定的访问器,称为get
和set
。
get { return _name; } set { _name = value; }
get
属性访问器用于返回属性值,set
访问器用于分配新值。value
关键字用于定义由setaccessor分配的值。
C#只读属性
为了创建只读属性,我们在实现中省略了set访问器并仅提供了get访问器。
var u = new User("John Doe", "gardener"); Console.WriteLine(u); class User { private string _name; private string _occupation; public User(string name, string occupation) { _name = name; _occupation = 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
关键字用于创建仅初始化属性;这些属性只能在对象构造期间初始化。
var u = new User("John Doe", "gardener"); Console.WriteLine(u); class User { public User(string name, string occupation) { Name = name; Occupation = occupation; } public string Name { get; init; } public string Occupation { get; init; } public override string ToString() { return $"{Name} is a {Occupation}"; } }
我们定义了两个init-only属性;它们在构造函数中初始化。之后,它们变得不可变。
public string Name { get; init; } public string Occupation { get; init; }
init-only属性是使用init
关键字创建的。
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";
我们在派生类中隐藏了一个成员。为了抑制编译器警告,我们使用new
关键字。
public override string Name { set { _name = value; } get { return _name; } }
在这里我们覆盖了Base
类的Name
属性。
在本文中,我们介绍了C#属性。
列出所有C#教程。