多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
# C# 属性 > 原文: [https://zetcode.com/lang/csharp/properties/](https://zetcode.com/lang/csharp/properties/) 在 C# 教程的这一部分中,我们将讨论属性。 属性是一种特殊的类成员。 我们使用预定义的设置和获取方法来访问和修改它们。 属性读取和写入会转换为获取和设置方法调用。 与使用自定义方法调用(例如`object.GetName()`)相比,使用字段符号(例如`object.Name`)访问变量更容易。 但是,就属性而言,我们仍然具有封装和信息隐藏的优势。 换句话说,属性可以保护数据免受外界干扰,同时可以方便地进行现场访问。 接口可以具有属性,但不能具有字段。 属性可以是读写的(它们既有获取和设置访问器),也可以是只读的(它们只有获取访问器)或只写(它们只有设置访问器)。 `Program.cs` ```cs using System; namespace SimpleProperties { class Person { private string _name; public string Name { get { return _name; } set { _name = value; } } } class Program { static void Main(string[] args) { var p = new Person(); p.Name = "Jane"; Console.WriteLine(p.Name); } } } ``` 我们有一个具有一个属性的简单`Person`类。 ```cs public string Name { ... } ``` 我们有一个称为`Name`的属性。 它看起来像一个常规方法声明。 不同之处在于,它具有称为`get`和`set`的特定访问器。 ```cs get { return _name; } set { _name = value; } ``` `get`属性访问器用于返回属性值,`set`访问器用于分配新值。 `value`关键字用于定义由设置索引器分配的值。 ```cs var p = new Person(); p.Name = "Jane"; Console.WriteLine(p.Name); ``` 我们创建`Person`类的实例。 我们使用字段符号访问成员字段。 ```cs $ dotnet run Jane ``` 这是该计划的结果。 ## C# 只读属性 可以创建只读属性。 为了创建一个只读属性,我们省略了 set 访问器,在实现中仅提供了 get 访问器。 `Program.cs` ```cs using System; namespace Readonly { class Person { private string _name = "Jane"; public string Name { get { return _name; } } } class Program { static void Main(string[] args) { var p = new Person(); // p.Name = "Beky"; Console.WriteLine(p.Name); } } } ``` 在前面的示例中,我们演示了只读属性的使用。 ```cs private string _name = "Jane"; ``` 我们立即初始化成员,因为以后不可能。 ```cs public string Name { get { return _name; } } ``` 通过仅提供一个 get 访问器,使该属性为只读。 ```cs // p.Name = "Beky"; ``` 现在此行已注释。 我们无法更改属性。 如果我们取消注释该行,则 C# 编译器将发出以下错误:`Program.cs(21,13): error CS0200: Property or indexer 'Person.Name' cannot be assigned to -- it is read only`。 ## C# 自动实现的属性 C# 具有自动实现或自动属性。 在软件项目中,有许多简单属性只能设置或获取一些简单值。 为了简化编程并简化代码,创建了自动属性。 注意,我们不能在所有情况下都使用自动属性。 仅适用于简单的。 `Program.cs` ```cs using System; namespace Autoimplemented { class Person { public string Name { get; set; } public int Age { get; set; } } class Program { static void Main(string[] args) { var p = new Person(); p.Name = "Jane"; p.Age = 17; Console.WriteLine($"{p.Name} is {p.Age} years old"); } } } ``` 该代码要短得多。 我们有一个`Person`类,其中有两个属性:`Name`和`Age`。 ```cs public string Name { get; set; } public int Age { get; set; } ``` 在这里,我们有两个自动属性。 没有访问器的实现,也没有成员字段。 编译器将为我们完成其余的工作。 ```cs var p = new Person(); p.Name = "Jane"; p.Age = 17; Console.WriteLine($"{p.Name} is {p.Age} years old"); ``` 我们通常照常使用这些属性。 ```cs $ dotnet run Jane is 17 years old ``` 这是示例的输出。 ## 表达式主体定义 从 C# 7.0 开始,可以使用表达式主体定义简化属性。 表达式主体定义由`=>`符号组成,后跟要分配给该属性或从该属性检索的表达式。 `Program.cs` ```cs using System; namespace ExpBodyDef { class User { string name; string occupation; public User(string name, string occupation) { this.name = name; this.occupation = occupation; } public string Name { get => name; set => name = value; } public string Occupation { get => occupation; set => occupation = value; } } class Program { static void Main(string[] args) { var u = new User("John Doe", "gardener"); Console.WriteLine($"{u.Name} is a {u.Occupation}"); } } } ``` 在示例中,我们使用表达式主体定义来定义`User`类的属性。 ```cs $ dotnet run John Doe is a gardener ``` 这是输出。 ## 其他注意事项 我们可以使用`public`,`private`或`protected`等访问修饰符标记属性。 属性也可以是`static`,`abstract`,`virtual`和`sealed`。 它们的用法与常规方法相同。 `Program.cs` ```cs using System; namespace OtherNotes { 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; } } } class Program { static void Main(string[] args) { var bs = new Base(); var dr = new Derived(); Console.WriteLine(bs.Name); Console.WriteLine(dr.Name); } } } ``` 在前面的示例中,我们定义了一个虚拟属性,并在`Derived`类中将其覆盖。 ```cs public virtual string Name { set { _name = value; } get { return _name; } } ``` 名称属性用`virtual`关键字标记。 ```cs protected new string _name = "Derived class"; ``` 我们将成员隐藏在`Derived`类中。 为了消除编译器警告,我们使用`new`关键字。 ```cs public override string Name { set { _name = value; } get { return _name; } } ``` 在这里,我们重写了`Base`类的`Name`属性。 本章介绍了 C# 属性。 我们描述了属性并显示了如何实现它们。 我们提到了自动属性和只读属性。