C#3.0新增功能01 自动实现的属性

在 C# 3.0 及更高版本,当属性访问器中不须要任何其余逻辑时,自动实现的属性会使属性声明更加简洁。 它们还容许客户端代码建立对象。 当你声明如下示例中所示的属性时,编译器将建立仅能够经过该属性的 get 和 set 访问器访问的专用、匿名支持字段。html

下列示例演示一个简单的类,它具备某些自动实现的属性:函数

// 该类是可变的。它的数据能够从类外部修改
class Customer { // 用于普通get和set的自动实现属性
    public double TotalPurchases { get; set; } public string Name { get; set; } public int CustomerID { get; set; } // 构造函数
    public Customer(double purchases, string name, int ID) { TotalPurchases = purchases; Name = name; CustomerID = ID; } // 方法
    public string GetContactInfo() { return "ContactInfo"; } public string GetTransactionHistory() { return "History"; } // 其余的方法、事件等
} class Program { static void Main() { // 初始化一个新对象
        Customer cust1 = new Customer(4987.63, "Northwind", 90108); // 修改属性
        cust1.TotalPurchases += 499.99; } }

在 C# 6 和更高版本中,你能够像字段同样初始化自动实现属性:spa

public string FirstName { get; set; } = "Jane";

上一示例中所示的类是可变的。 建立客户端代码后能够用于更改对象中的值。 在包含重要行为(方法)以及数据的复杂类中,一般有必要具备公共属性。 可是,对于较小类或仅封装一组值(数据)且只有不多行为或没有行为的结构,则应该经过声明 set 访问器为专用(对使用者的不可变)或经过声明仅一个 get 访问器(除构造函数外都不可变),使对象不可变。调试

使用自动实现的属性实现轻量类

本示例演示如何建立一个仅用于封装一组自动实现的属性的不可变轻型类。 当你必须使用引用类型语义时,请使用此种构造而不是结构。code

可经过两种方法来实现不可变的属性:htm

  • 能够将 set 访问器声明为专用。 属性只能在该类型中设置,但它对于使用者是不可变的。对象

    当你声明一个 private set 取值函数时,你没法使用对象初始值设定项来初始化属性。你必须使用构造函数或工厂方法。blog

  • 也能够仅声明 get 访问器,使属性除了能在该类型的构造函数中可变,在其余任何位置都不可变。事件

下面的示例演示了实现具备自动实现属性的不可变类的两种方法。 这两种方法均使用 private set 声明其中一个属性,使用单独的 get 声明另外一个属性。 第一个类仅使用构造函数来初始化属性,第二个类则使用可调用构造函数的静态工厂方法。ci

 1 // 这个类是不可变的。建立对象后,不能从类外部修改它。它使用构造函数初始化其属性。
 2 class Contact  3 {  4     // 公共只读属性
 5     public string Name { get; }  6     public string Address { get; private set; }  7 
 8     // 公共构造函数
 9     public Contact(string contactName, string contactAddress) 10  { 11         Name = contactName; 12         Address = contactAddress; 13  } 14 } 15 
16 // 这个类是不可变的。建立对象后,不能从类外部修改它。它使用静态方法和私有构造函数初始化其属性。
17 public class Contact2 18 { 19     // 公共只读属性
20     public string Name { get; private set; } 21     public string Address { get; } 22 
23     // 私有构造函数
24     private Contact2(string contactName, string contactAddress) 25  { 26         Name = contactName; 27         Address = contactAddress; 28  } 29 
30     // 共有工厂方法
31     public static Contact2 CreateContact(string name, string address) 32  { 33         return new Contact2(name, address); 34  } 35 } 36 
37 public class Program 38 { 39     static void Main() 40  { 41         string[] names = {"Terry Adams","Fadi Fakhouri", "Hanying Feng", 42                           "Cesar Garcia", "Debra Garcia"}; 43         string[] addresses = {"123 Main St.", "345 Cypress Ave.", "678 1st Ave", 44                               "12 108th St.", "89 E. 42nd St."}; 45 
46         // 在 select 子句中演示对象建立的简单查询。使用构造函数建立contact对象。
47         var query1 = from i in Enumerable.Range(0, 5) 48                      select new Contact(names[i], addresses[i]); 49 
50         // 列表元素不能由客户端代码修改。
51         var list = query1.ToList(); 52         foreach (var contact in list) 53  { 54             Console.WriteLine("{0}, {1}", contact.Name, contact.Address); 55  } 56 
57         // 使用静态工厂方法建立contact2对象。
58         var query2 = from i in Enumerable.Range(0, 5) 59                      select Contact2.CreateContact(names[i], addresses[i]); 60 
61         // 控制台输出与query1相同。
62         var list2 = query2.ToList(); 63 
64         // 列表元素不能由客户端代码修改。 65         // CS0272: 66         // list2[0].Name = "Eugene Zabokritski"; 67 
68         // 在调试模式下保持控制台打开。
69         Console.WriteLine("Press any key to exit."); 70  Console.ReadKey(); 71  } 72 } 73 
74 /* 输出: 75  Terry Adams, 123 Main St. 76  Fadi Fakhouri, 345 Cypress Ave. 77  Hanying Feng, 678 1st Ave 78  Cesar Garcia, 12 108th St. 79  Debra Garcia, 89 E. 42nd St. 80 */

编译器为每一个自动实现的属性建立了支持字段。 这些字段没法直接从源代码进行访问。

 

相关文章
相关标签/搜索