属性
属性时一种成员,它提供灵活的机制来读取、写入或计算私有字段的值。属性可用作公共数据成员,但它们实际上是成为访问器的特殊方法。这使得可以轻松访问数据,有助于提高方法的安全性和灵活性。
属性概述
- 属性允许公开获得和设置值的公共方法,而隐藏实现或验证代码
- get属性访问器用于返回属性值,而set属性访问器用于分配值。
- value关键字用于定义由set或init访问器分配的值。
- 属性可以是读-写属性(即有get访问器又有set访问器)、只读属性(有get访问器,但没有set访问器)或只写(有set访问器,但没有get访问器)。只写属性很少出现,常用于限制对敏感数据的访问
- 不需要自定义访问器代码的简单属性可以作为表达式主题定义或自动实现的属性来实现
具有支持字段的属性
有一个实现属性的基本模式,该模式使用私有支持字段来设置和检索属性值。get访问器返回私有字段的值,set访问器在向私有字段赋值之前可能会执行一些数据验证。这两个访问器还可以在存储或返回数据之前对其执行某些转换或计算。
下面的示例阐释了此模式。在此示例中,TimePeriod类表示时间间隔。在内部,该类将时间间隔以秒为单位存储在名为_seconds的私有字段中。名为Hours的读-写属性允许客户以小时为单位指定的时间间隔。get和set访问器都会执行小时和秒之间的必要转换。此外,set访问器还会验证数据,如果小时无效,则会引发异常
using System;
namespace _97属性和字段
{
internal class Program
{
static void Main(string[] args)
{
TimePerid t = new TimePerid();
t.Hours = 24;
Console.WriteLine($"Time in hours:{t.Hours}");
Console.Read();
}
}
class TimePerid
{
private double _seconds;
public double Hours
{
get { return _seconds / 3600; }
set
{
if (value < 0 || value > 24)
{
throw new ArgumentOutOfRangeException($"{nameof(value)} must be between 0 and 24.");
}
_seconds = value * 3600;
}
}
}
}
表达式主题定义
属性访问器通常由单行语句组成,这些语句只分配或返回表达式的结果。可以将这些属性作为expression-bodied成员来实现。=>符号后跟用于为属性赋值或从属性中检索值的表达式,即组成了表达式主题定义。
从C#6开始,只读属性可以将get访问器作为expression-bodied成员实现。在这种情况下,即不适用get访问器关键字,也不适用return关键字。下面的示例代码将制度Name属性作为expression-bodied成员实现。
using System;
namespace _96属性字段_表达式主题定义
{
internal class Program
{
static void Main(string[] args)
{
var person = new Person("xu", "xiao bai");
Console.WriteLine(person.Name);
Console.Read();
}
}
class Person
{
private string _firstName;
private string _lastName;
public Person(string first, string last)
{
_firstName = first;
_lastName = last;
}
public string Name => $"{_firstName} {_lastName} ";
}
}
C# 7.0开始,get和set访问器都可以作为expression-bodied成员实现。在这种情况下,必须使用get和set关键字。下面的示例阐释如何为这两个访问器使用表达主题定义。请注意,return关键字不与get访问器搭配使用
using System;
namespace _95属性字段_表达式主题定义
{
internal class Program
{
static void Main(string[] args)
{
var item = new SaleItem("Shoes", 20.2m);
Console.WriteLine($"{item.Name}:sells for {item.Price:C2}");
Console.Read();
}
}
public class SaleItem
{
string _name;
decimal _cost;
public SaleItem(string name, decimal cost)
{
_name = name;
_cost = cost;
}
public string Name
{
get => _name;
set => _name = value;
}
public decimal Price
{
get => _cost;
set => _cost = value;
}
}
}
自动实现的属性
在某些情况下,属性 get 和 set 访问器仅向支持字段赋值或仅从其中检索值,而不包括任何附加逻辑。 通过使用自动实现的属性,既能简化代码,还能让 C# 编译器透明地提供支持字段。
如果属性具有 get 和 set(或 get 和 init)访问器,则必须自动实现这两个访问器。 自动实现的属性通过以下方式定义:使用 get 和 set 关键字,但不提供任何实现。 下面的示例与上一个示例基本相同,只不过 Name 和 Price 是自动实现的属性。 该示例还删除了参数化构造函数,以便通过调用无参数构造函数和对象初始值设定项立即初始化 SaleItem 对象。
using System;
public class SaleItem
{
public string Name
{ get; set; }
public decimal Price
{ get; set; }
}
class Program
{
static void Main(string[] args)
{
var item = new SaleItem{ Name = "Shoes", Price = 19.95m };
Console.WriteLine($"{item.Name}: sells for {item.Price:C2}");
}
}
// The example displays output like the following:
// Shoes: sells for $19.95