C# 定義屬性
屬性的定義方式與字段類似,但包含的內(nèi)容比較多。如前所述,屬性比字段復(fù)雜,因?yàn)樗鼈冊谛薷臓顟B(tài)前還可以執(zhí)行一些額外操作,實(shí)際上,它們可能并不修改狀態(tài)。屬性擁有兩個(gè)類似于函數(shù)的塊,一個(gè)塊用于獲取屬性的值,另一個(gè)塊用于設(shè)置屬性的值。
這兩個(gè)塊也稱為訪問器,分別用get和set關(guān)鍵字來定義,可以用于控制屬性的訪問級別。可以忽略其中的一個(gè)塊來創(chuàng)建只讀或只寫屬性(忽略get塊創(chuàng)建只寫屬性,忽略set塊創(chuàng)建只讀屬性)。當(dāng)然,這僅適用于外部代碼,因?yàn)轭愔械钠渌a可以訪問這些代碼塊能訪問的數(shù)據(jù),還可以在訪問器上包含可訪問修飾符,例如使get塊變成公共的,使set塊變成受保護(hù)的,至少要包含其中一個(gè)塊,屬性才是有效的(既不能讀取也不能修改的屬性沒有任何用處)。
屬性的基本結(jié)構(gòu)包括標(biāo)準(zhǔn)的可訪問修飾符(public、private等),后跟類型名、屬性名和get塊(或set塊,或者get塊和set塊,其中包含屬性處理代碼),例如:
public int MylntProp
{
get
{
// Property get code.
}
set
{
// Property set code.
}
}
定義中的第一行代碼非常類似于定義字段的代碼,區(qū)別在于行末沒有分號,而是一個(gè)包含嵌套get和set塊的代碼塊。
getM、須有一個(gè)屬性類型的返回值,簡單屬性一般與私有字段相關(guān)聯(lián),以控制對這個(gè)字段的訪問,此時(shí)get塊可以直接返回該字段的值,例如:
// Field used by property.
private int mylnt;
// Property.
public int MylntProp
{
get { return mylnt; }
set { // Property set code. }
}
類外部的代碼不能直接訪問這個(gè)mylnt字段,因?yàn)槠湓L問級別是私有的。外部代碼必須使用屬性來訪問該字段。set函數(shù)采用類似方式把一個(gè)值賦給字段。這里可使用關(guān)鍵字value來表示用戶提供的屬性值:
// Field used by property.
private int mylnt;
// Property.
public int MylntProp
{
get { return mylnt; }
set { mylnt = value; }
}
value等于類型與屬性相同的一個(gè)值,所以如果屬性和字段使用相同的類型,就不必考慮數(shù)據(jù)類型轉(zhuǎn)換了。要為可空整數(shù)類型提供一個(gè)默認(rèn)值,可以使用這個(gè)由表達(dá)式構(gòu)成的成員函數(shù)模式。
private int? mylnt;
public int? MylntProp
{
get { return mylnt;)
set { mylnt = value ?? 0; }
}
這個(gè)簡單屬性只是用來阻止對mylnt字段的直接訪問。在對操作進(jìn)行更多控制時(shí),屬性的真正作用才能發(fā)揮出來。例如,使用下面的代碼實(shí)現(xiàn)set塊:
set
{
if (value >- 0 && value <= 10)
mylnt = value;
}
只有賦給屬性的值在0~10之間,才會(huì)修改mylnt。此時(shí),要做一個(gè)重要的設(shè)計(jì)選擇:如果使用了無效值,該怎么辦?有4種選擇:
?什么也不做(如上述代碼所示)。
?給字段賦默認(rèn)值。
?繼續(xù)執(zhí)行,就像沒發(fā)生錯(cuò)誤一樣,但記錄下該事件,以備將來分析。
?拋出異常。
—般情況下,后兩個(gè)選擇效果較好,選擇哪個(gè)選項(xiàng)取決于如何使用類,以及給類的用戶授予多少控制權(quán)。 拋出異常給用戶提供的控制權(quán)相當(dāng)大,可以讓他們了解發(fā)生了什么情況,并做適當(dāng)?shù)捻憫?yīng)。為此可使用System名稱空間中的標(biāo)準(zhǔn)異常,例如:
set
{
if (value >= 0 && value <= 10)
mylnt = value;
else
throw (new ArgumentOutOfRangeException("MylntProp11, value,
"MylntProp must be assigned a value between 0 and 10."}};
該異常可在使用屬性的代碼中通過try...catch...finally邏輯加以處理。
記錄數(shù)據(jù)(例如記錄到文本文件中或Event Log中)比較有效,例如可用在不應(yīng)出錯(cuò)的產(chǎn)品代碼中。它們允許開發(fā)人員檢查性能,如有必要,還可以調(diào)試現(xiàn)有的代碼。
屬性可以使用virtual、override和abstract關(guān)鍵字,就像方法一樣,但這幾個(gè)關(guān)鍵字不能用于字段。最后,如上所述,訪問器可以有自己的可訪問性,例如:
// Field used by property.
private int mylnt;
// Property.
public int MylntProp
{
get { return myint; }
protected set { mylnt = value; }
}
只有類或派生類中的代碼才能使用set訪問器。
訪問器可以使用的訪問修飾符取決于屬性的可訪問性,訪問器的可訪問性不能高于它所屬的屬性,也就是說, 私有屬性對它的訪問器不能包含任何可訪問修飾符,而公共屬性可以對其訪問器使用所有的可訪問修飾符。
C# 6引入了一個(gè)名為“基于表達(dá)式的屬性”的功能.類似于第6章討論的基于表達(dá)式的方法,這個(gè)功能可以把屬性的定義減少為一行代碼。例如,下面的屬性對一個(gè)值進(jìn)行數(shù)學(xué)計(jì)算,可以使用Lambda箭頭后跟等式來定義:
// Field used by property.
private int myDoubledint = 5;
// Property.
public int MyDoubledlntProp => (myDoubledlnt * 2);
點(diǎn)擊加載更多評論>>