屬性
屬性是一種成員,它提供靈活的機制來讀取、寫入或計算私有字段的值。屬性可用作公共數據成員,但它們實際上是稱為“訪問器”的特殊方法。這使得可以輕松訪問數據,還有助于提高方法的安全性和靈活性。
在此示例中,TimePeriod 類存儲時間段。該類在內部以秒為單位存儲時間,但是名為 Hours 的屬性允許客戶端以小時為單位指定時間。 Hours 屬性的訪問器執行小時與秒之間的轉換。
class TimePeriod{ private double seconds; public double Hours { get { return seconds / 3600; } set { seconds = value * 3600; } }}class Program{ static void Main() { TimePeriod t = new TimePeriod(); // Assigning the Hours property causes the 'set' accessor to be called. t.Hours = 24; // Evaluating the Hours property causes the 'get' accessor to be called. System.Console.WriteLine("Time in hours: " + t.Hours); }}
輸出:
Time in hours: 24
表達式主體定義
直接只返回表達式結果的屬性很常見。下面的語法快捷方式使用 => 來定義這些屬性:
public string Name => First + " " + Last;
屬性必須為只讀,并且你不能使用 get 訪問器關鍵字。
使用屬性
屬性結合了字段和方法的多個方面。對于對象的用戶,屬性顯示為字段,訪問該屬性需要相同的語法。對于類的實現者,屬性是一個或兩個代碼塊,表示一個 get 訪問器和/或一個 set 訪問器。當讀取屬性時,執行 get 訪問器的代碼塊;當向屬性分配一個新值時,執行 set 訪問器的代碼塊。不具有 set 訪問器的屬性被視為只讀屬性。不具有 get 訪問器的屬性被視為只寫屬性。同時具有這兩個訪問器的屬性是讀寫屬性。
屬性具有多種用法:它們可在允許更改前驗證數據;它們可透明地公開某個類上的數據,該類的數據實際上是從其他源(例如數據庫)檢索到的;當數據被更改時,它們可采取行動,例如引發事件或更改其他字段的值。
屬性在類塊中是按以下方式來聲明的:指定字段的訪問級別,接下來指定屬性的類型和名稱,然后跟上聲明 get 訪問器和/或 set 訪問器的代碼塊。例如:
public class Date{ private int month = 7; // Backing store public int Month { get { return month; } set { if ((value > 0) && (value < 13)) { month = value; } } }}
在此示例中,Month 是作為屬性聲明的,這樣 set 訪問器可確保 Month 值設置為 1 和 12 之間。 Month 屬性使用私有字段來跟蹤該實際值。屬性的數據的真實位置經常稱為屬性的“后備存儲”。屬性使用作為后備存儲的私有字段是很常見的。將字段標記為私有可確保該字段只能通過調用屬性來更改。
。
get 訪問器
get 訪問器體與方法體相似。它必須返回屬性類型的值。執行 get 訪問器相當于讀取字段的值。例如,當正在從 get 訪問器返回私有變量并且啟用了優化時,對 get 訪問器方法的調用由編譯器進行內聯,因此不存在方法調用的系統開銷。然而,由于在編譯時編譯器不知道在運行時實際調用哪個方法,因此無法內聯虛擬 get 訪問器。以下是返回私有字段 name 的值的 get 訪問器:
class Person{ private string name; // the name field public string Name // the Name property { get { return name; } }}
當引用屬性時,除非該屬性為賦值目標,否則將調用 get 訪問器以讀取該屬性的值。例如:
Person person = new Person();//...System.Console.Write(person.Name); // the get accessor is invoked here
get 訪問器必須以 return 或 throw 語句終止,并且控制權不能離開訪問器體。
通過使用 get 訪問器更改對象的狀態不是一種好的編程風格。例如,以下訪問器在每次訪問 number 字段時都會產生更改對象狀態的副作用。
private int number;public int Number{ get { return number++; // Don't do this }}
get 訪問器可用于返回字段值,或用于計算并返回字段值。例如:
class Employee{ private string name; public string Name { get { return name != null ? name : "NA"; } }}
在上一個代碼段中,如果不對 Name 屬性賦值,它將返回值 NA。
set 訪問器
set 訪問器類似于返回類型為 void 的方法。它使用稱為 value 的隱式參數,此參數的類型是屬性的類型。在下面的示例中,將 set 訪問器添加到 Name 屬性:
class Person{ private string name; // the name field public string Name // the Name property { get { return name; } set { name = value; } }}
當對屬性賦值時,用提供新值的參數調用 set 訪問器。例如:
Person person = new Person();person.Name = "Joe"; // the set accessor is invoked here System.Console.Write(person.Name); // the get accessor is invoked here
在 set 訪問器中,對局部變量聲明使用隱式參數名稱 value 是錯誤的。
此例說明了實例、靜態和只讀屬性。它從鍵盤接受雇員的姓名,按 1 遞增 NumberOfEmployees,并顯示雇員的姓名和編號。
public class Employee{ public static int NumberOfEmployees; private static int counter; private string name; // A read-write instance property: public string Name { get { return name; } set { name = value; } } // A read-only static property: public static int Counter { get { return counter; } } // A Constructor: public Employee() { // Calculate the employee's number: counter = ++counter + NumberOfEmployees; }}class TestEmployee{ static void Main() { Employee.NumberOfEmployees = 107; Employee e1 = new Employee(); e1.Name = "Claude Vige"; System.Console.WriteLine("Employee number: {0}", Employee.Counter); System.Console.WriteLine("Employee name: {0}", e1.Name); }}
輸出:
Employee number: 108 Employee name: Claude Vige
此示例說明如何訪問基類中由派生類中具有同一名稱的另一個屬性所隱藏的屬性。
public class Employee{ private string name; public string Name { get { return name; } set { name = value; } }}public class Manager : Employee{ private string name; // Notice the use of the new modifier: public new string Name { get { return name; } set { name = value + ", Manager"; } }}class TestHiding{ static void Main() { Manager m1 = new Manager(); // Derived class property. m1.Name = "John"; // Base class property. ((Employee)m1).Name = "Mary"; System.Console.WriteLine("Name in the derived class is: {0}", m1.Name); System.Console.WriteLine("Name in the base class is: {0}", ((Employee)m1).Name); }}
輸出:
Name in the derived class is: John, Manager Name in the base class is: Mary
以下是上一個示例中的要點:
派生類中的屬性 Name 隱藏基類中的屬性 Name。在這種情況下,派生類的屬性聲明中使用 new 修飾符:
public new string Name
轉換 (Employee) 用于訪問基類中的隱藏屬性:
((Employee)m1).Name = "Mary";
在此例中,Cube 和 Square 這兩個類實現抽象類 Shape,并重寫它的抽象 Area 屬性。注意屬性上 override 修飾符的使用。程序接受輸入的邊長并計算正方形和立方體的面積。它還接受輸入的面積并計算正方形和立方體的相應邊長。
abstract class Shape{ public abstract double Area { get; set; }}class Square : Shape{ public double side; public Square(double s) //constructor { side = s; } public override double Area { get { return side * side; } set { side = System.Math.Sqrt(value); } }}class Cube : Shape{ public double side; public Cube(double s) { side = s; } public override double Area { get { return 6 * side * side; } set { side = System.Math.Sqrt(value / 6); } }}class TestShapes{ static void Main() { // Input the side: System.Console.Write("Enter the side: "); double side = double.Parse(System.Console.ReadLine()); // Compute the areas: Square s = new Square(side); Cube c = new Cube(side); // Display the results: System.Console.WriteLine("Area of the square = {0:F2}", s.Area); System.Console.WriteLine("Area of the cube = {0:F2}", c.Area); System.Console.WriteLine(); // Input the area: System.Console.Write("Enter the area: "); double area = double.Parse(System.Console.ReadLine()); // Compute the sides: s.Area = area; c.Area = area; // Display the results: System.Console.WriteLine("Side of the square = {0:F2}", s.side); System.Console.WriteLine("Side of the cube = {0:F2}", c.side); }}
輸出:
Enter the side: 4 Area of the square = 16.00 Area of the cube = 96.00 Enter the area: 24 Side of the square = 4.90 Side of the cube = 2.00
新聞熱點
疑難解答