[C#参考]属性
属性和字段不同,属性是一个函数成员:它提供灵活的机制来读取、编写或计算某个私有字段的值。 可以像使用公共数据成员一样使用属性,但实际上它们是称作“访问器”的特殊方法。 这使得可以轻松访问数据,此外还有助于提高方法的安全性和灵活性。
属性不为数据存储分配内存空间,它是执行代码。
意思是如果我们想封装类的成员变量,但是我们总不能把所有的变量都封装的死死的,不允许外面的任何人看到,这是不合理的。
例如有一个person类,它的属性有姓名、性别、年龄等。我要访问某个对象的性别,或者设置某个对象的性别。
外部的对象要实现,对它的访问,有三种方法:
1.把属性改正public的权限,这样任何人都能看到或者修改这个属性,这样很简洁,但是出现的问题是安全性降低,比如我对这个字段赋值“牛”,那么这个对象的的性别字段就是“牛”了,显然不合理。
2.仍然保持字段的private私有属性,编写一个方法实现字段的修改,但是这样以来,外部对象访问内部私有对象的时候,很麻烦,必须调用set()或者get()方法。那么就寻求一种方法,能不公开私有字段,同时又能很简洁的调用,就好像是在直接访问成员字段一样,所以就引入了第三种方法:属性。
3.属性封装字段数据,对象的字段保持其private的访问权限,利用属性实现封装,好像直接访问成员字段一样供外部对象使用。但是本质上仍然是通过类的成员方法访问才实现的。属性也是类的成员,但是它是私有地段的封装,只是私有字段的一个对外的接口,它能通过一些逻辑保证私有字段访问的安全机制,同时又不会像第2种方法那样使用用户不友好的接口。能像直接访问私有字段一样访问。
在本示例中,TimePeriod 类存储一个时间段。 在内部,类以秒为单位存储时间,但客户端使用名为 Hours 的属性能够以小时为单位指定时间。 Hours 属性的访问器执行小时和秒之间的转换。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class TimePeriod 2 { 3 private double seconds; 4 5 public double Hours 6 { 7 get { return seconds / 3600; } 8 set { seconds = value * 3600; } 9 } 10 } 11 12 13 class Program 14 { 15 static void Main() 16 { 17 TimePeriod t = new TimePeriod(); 18 19 // Assigning the Hours property causes the 'set' accessor to be called. 20 t.Hours = 24; 21 22 // Evaluating the Hours property causes the 'get' accessor to be called. 23 System.Console.WriteLine("Time in hours: " + t.Hours); 24 } 25 } 26 // Output: Time in hours: 24
value 关键字用于定义由 set 取值函数分配的值。
我们可以设置访问修饰符限制get和set方法的访问权限,为此,属性必须既有set又有get访问方法,而且只能限制其中之一,修饰符必须必属性本身已有的访问权限要严格。
此示例演示如何创建一个不可变轻量类,用于仅封装一组自动实现的属性。 当您必须使用引用类型语义时,请使用此种构造而不是结构。
请注意:对于自动实现的属性,需要 get 和 set 访问器。 要使该类不可变,请将 set 访问器声明为 private。 但是,声明私有 set 访问器时,不能使用对象初始值来初始化属性。 必须使用构造函数或工厂方法。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 // This class is immutable. After an object is created, 2 // it cannot be modified from outside the class. It uses a 3 // constructor to initialize its properties. 4 class Contact 5 { 6 // Read-only properties. 7 public string Name { get; private set; } 8 public string Address { get; private set; } 9 10 // Public constructor. 11 public Contact(string contactName, string contactAddress) 12 { 13 Name = contactName; 14 Address = contactAddress; 15 } 16 } 17 18 // This class is immutable. After an object is created, 19 // it cannot be modified from outside the class. It uses a 20 // static method and private constructor to initialize its properties. 21 public class Contact2 22 { 23 // Read-only properties. 24 public string Name { get; private set; } 25 public string Address { get; private set; } 26 27 // Private constructor. 28 private Contact2(string contactName, string contactAddress) 29 { 30 Name = contactName; 31 Address = contactAddress; 32 } 33 34 // Public factory method. 35 public static Contact2 CreateContact(string name, string address) 36 { 37 return new Contact2(name, address); 38 } 39 }
前面说了,属性只是封装数据字段,编译器为每个自动实现的属性创建了后备字段。 这些字段无法直接从源代码进行访问。