C#學習筆記(定義屬性get&set)


  屬性擁有兩個類似於函數的塊,一個塊用於獲取屬性的值,另一個塊用於設置屬性的值。這兩個塊也稱為訪問器,分別用get和set關鍵字來定義,可以用於控制對屬性的訪問級別。可以忽略其中的一個塊來創建只讀或只寫屬性(忽略get塊創建只寫屬性,忽略set塊創建只讀屬性)。當然,這僅適用於外部代碼,因為類中的其他代碼可以訪問的數據。還可以在訪問器上包含可訪問修飾符,例如使get塊變成公共的,把set塊變成保護的。只有包含其中一個一個塊,才能獲得有效屬性(既不能讀取也不能修改的屬性沒有任何用途)。

  屬性的基本結構包括標准的可訪問修飾符(public、private等),后跟類名、屬性和get塊(或set塊,或者get塊和set塊,其中包含屬性處理代碼)。

public int myIntProp

{

  get

  {

    //Property get code.

  }

  set

  {

    //Property set code.

  }

} 

1 get關鍵字

  get塊必須有一個屬性的返回值,簡單的屬性一般與私有字段相關聯,以控制對這個字段的訪問,此時get塊可以直接返回該字段的值,例如:

private int myInt;

public int myIntProp

{

  get

  {

    return myInt;

  }

  set

  {

    //Property set code.

  }

}

  類外部的代碼不能直接訪問這個myInt字段,私有的,必須使用屬性來訪問該字段。

2 set關鍵字

  set函數以類似的方法把一個值賦給字段。這里使用value表示用戶提供的屬性值:

private int myInt;

public int myIntProp

{

  get 

  {

    return myInt;

  }

  set

  {

    myInt = value;

  }

}

  value等於類似與屬性相同的值,所以如果屬性和字段使用相同的類型,就不必擔心數據類型轉換了。

  這個簡單的屬性只能直接訪問myInt字段。在對操作進行更多的控制的時候,屬性的真正作用才能發揮出來,例如,使用下面的代碼實現set塊:

set

{

  if(value >= 0 && value <= 10)

    myInt = value;

}

  只用賦給屬性的值在1~10之間,才會改myInt。此時,要做一個重要的設計選擇:如果使用了無效值,該怎么辦:

  • 什么也不做
  • 給字段賦默認值
  • 繼續執行,就好像沒有發生錯誤一樣,但記錄下來該事件,以備將來分析
  • 拋出異常

  一般情況下,后面兩個選擇效果較好,選擇哪個選項取決於如何使用類,以及給用戶授予多少控制權。拋出異常給用戶提供的控制權相當的大,例如:
set

{

  if(value >= 0 && value <= 10)

    myInt = value;

  else

    throw (new ArgumentOutOfRangeException("myIntProp",value,"myIntProp must be assigned a value between 0 and 10."))

}

  這可以在使用屬性的代碼中通過try...catch...finaly邏輯來處理。

注:屬性可以使用virtual、override和abstract關鍵字,就像方法一樣,但這幾個關鍵字不能用於字段。最后,如上述,訪問器可以有自己的訪問性。

實例:

public class MyClass
{
public readonly string Name;
private int intVal;

public int Val
{
  get
  {
  return intVal;
  }
  set
  {
    if (value >= 0 && value <= 10 )
      intVal = value;
    else
      throw (new ArgumentOutOfRangeException("Val",value,"Val must be assigned a value between 0 ang 10."));
  }
}
public override string ToString()
{
  return "Name:"+Name+"\nVal:"+Val;
}
private MyClass(): this("Default Name")
{

}
public MyClass(string newName)
{
  Name = newName;
  intVal = 0;
}
}

 

static void Main(string[] args)
{
  Console.WriteLine("Creating object myobj...");
  MyClass myObj = new MyClass("My Object");
  Console.WriteLine("myObj created.");
  for (int i = -1; i <= 0; i++ )
  {
    try
    {
      Console.WriteLine("\nAttempting to assign {0} to myObj.val...",i);
      myObj.Val = i;
      Console.WriteLine("Value {0} assigned to myObj.val.", myObj.Val);
    }
    catch(Exception e)
    {
      Console.WriteLine("Exception {0} throw.",e.GetType().FullName);
      Console.WriteLine("Message:\n\"{0}\"",e.Message);
    }
  }
  Console.WriteLine("\nOutputting myObj.ToString()...");
  Console.WriteLine(myObj.ToString());
  Console.WriteLine("myObj.ToString() Output.");
  Console.ReadKey();
}

  Main()中的的代碼創建並使用在MyClass.cs中定義的MyClass類的實例。實例化這個類必須使用非默認的構造函數來進行,因為MyClass類的默認構造函數是私有的。

  Main()試着給myObj(MyClass的實例)的Val屬性賦值。for循環在兩次中賦值-1和0,try..catch...結構用於檢測拋出的異常。把-1賦給屬性時,會拋出System.ArgumentOutOfException類型的異常,catch塊中的代碼會把改異常的信息輸出到控制台窗口中。在下一個循環中,值0成功的賦給了Val屬性,通過這個屬性再把值賦給私有字段intVal。

3 自動屬性

  屬性是訪問對象狀態的首選方式,因為他們禁止外部代碼實現對象內部的數據存儲機制。屬性還對內部數據的訪問事施加了更多的控制,但是,一般以非常標准的方式屬性,即通過一個公共屬性來訪問一個私有成員。其代碼非常類似於前面的代碼,這是VS重構工具自動生成的。

  重構功能肯定加快了鍵入的速度,C#還為此提供了另一種方式:自動屬性。利用自動屬性,可以用簡化的語法聲明屬性,C#編譯器會自動添加未鍵入的內容,具體而言,編譯器會聲明一個用於存儲屬性的私有字段,並在屬性的get和set塊中使用該字段,我們無需考慮細節。

public int MyIntProp

{

  get;

  set;

}

  我們按照通常的方式定義屬性的可訪問性、類型和名稱。但是沒有給get和set塊提供實現的代碼。這些塊的實現代碼(和底層的字段)由編譯器提供。

  使用自動屬性時,只能通過屬性訪問數據,不能通過底層的私有字段來訪問,我們不知道底層私有字段的名稱(該名稱是編譯期間定義的)。但這並不是一個真正意義上的限制,因為可以直接使用屬性名。自動屬性的唯一限制是他們必須包含get和set存儲器,無法使用這種方法定義只讀和只寫屬性。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM