屬性
屬性提供一種功能強大的方法,可將中繼資料或宣告資訊關聯至程式碼 (組建、型別、方法、屬性等)。 將屬性關聯至程式實體之後,就能在執行階段使用稱為「反映」的技術來查詢該屬性。
屬性 (Attribute) 包含下列屬性 (Property):
- 屬性會將中繼資料新增至您的程式。 「中繼資料」是在程式中定義的型別相關資訊。 所有的 .NET 組件都包含一組指定的中繼資料,來描述組件中所定義的型別和型別成員。 您可以新增自訂屬性來指定所需的任何其他資訊。
- 您可以將一或多個屬性 (Attribute) 套用至整個組件、模組或較小的程式元素,例如類別和屬性 (Property)。
- 屬性 (Attribute) 可以利用與方法與屬性 (Property) 相同的方式來接受引數。
- 您的程式可以使用反映,來檢查自己的中繼資料或其他程式的中繼資料。
反映提供的物件 (類型為 Type) 可描述組件、模組和型別。 您可以使用反映來動態建立類型的執行個體、將類型繫結至現有的物件,或從現有的物件取得類型,並叫用其方法或存取其欄位及屬性。 如果在程式碼中使用屬性,反映即可讓您存取這些屬性。 如需詳細資訊,請參閱屬性。
以下是簡易的反映範例,此範例使用 GetType() 方法 (由 Object
基底類別的所有型別繼承),以取得變數型別:
注意
請確定您在 .cs 檔案頂端新增 using System;
和 using System.Reflection;
。
// Using GetType to obtain type information:
int i = 42;
Type type = i.GetType();
Console.WriteLine(type);
輸出為:System.Int32
。
下列範例使用反映以取得所載入組件的完整名稱。
// Using Reflection to get information of an Assembly:
Assembly info = typeof(int).Assembly;
Console.WriteLine(info);
輸出類似:System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
。
注意
C# 關鍵字 protected
和 internal
在中繼語言 (IL) 中沒有任何意義,而且不會用於反映 API。 IL 中的對應詞彙是「系列」和「組件」。 若要使用反映來識別 internal
方法,請使用 IsAssembly 屬性。 若要識別 protected internal
方法,請使用 IsFamilyOrAssembly。
使用屬性
屬性可以放置於絕大多數的任意宣告中,但特定的屬性可能會限制其適用的宣告型別。 在 C# 中,指定屬性的方式是以方括弧 ([]
) 括住屬性名稱,並放置在要套用的實體宣告上方。
在此範例中,會使用 SerializableAttribute 屬性來將特定的特性套用至類別:
[Serializable]
public class SampleClass
{
// Objects of this type can be serialized.
}
具有 DllImportAttribute 屬性的方法會如下範例宣告:
[System.Runtime.InteropServices.DllImport("user32.dll")]
extern static void SampleMethod();
多個屬性可以放在宣告,如下列範例所示:
void MethodA([In][Out] ref double x) { }
void MethodB([Out][In] ref double x) { }
void MethodC([In, Out] ref double x) { }
可以針對特定實體多次指定某些屬性。 ConditionalAttribute 就是這種多次使用屬性的一個例子:
[Conditional("DEBUG"), Conditional("TEST1")]
void TraceMethod()
{
// ...
}
注意
依照慣例,所有的屬性名稱都會以 "Attribute" 這個字結尾,以便與 .NET 程式庫中的其他項目有所區別。 不過,您在程式碼中使用屬性時,不需要指定屬性的後置詞。 例如,[DllImport]
相當於 [DllImportAttribute]
,但 DllImportAttribute
是屬性在 .NET 類別庫中的實際名稱。
屬性參數
許多屬性的參數可以是位置、未命名或具名的參數。 任何位置的參數必須以特定順序指定,而且不能省略。 具名的參數是選擇性的,可以依照任何順序指定。 位置參數會先指定。 例如,這三個屬性是相等的:
[DllImport("user32.dll")]
[DllImport("user32.dll", SetLastError=false, ExactSpelling=false)]
[DllImport("user32.dll", ExactSpelling=false, SetLastError=false)]
第一個參數 (DLL 名稱) 是位置參數,一律會先出現;其他的則為具名參數。 在此案例中,這兩個具名參數預設為 false,因此可以省略。 位置參數對應至屬性建構函式的參數。 對應屬性或欄位屬性的具名或選擇性參數。 請參閱個別屬性的文件,以取得預設參數值的詳細資訊。
如需允許的參數型別詳細資訊,請參閱 C# 語言規格的屬性一節
屬性目標
屬性的目標是要套用屬性的實體。 例如,屬性可套用至類別、特定的方法或整個組件。 根據預設,屬性會套用到位於其後方的元素。 但是,舉例來說,您也可以明確地識別是否要將屬性套用到方法、它的參數或它的傳回值。
若要明確地識別屬性目標,請使用下列語法:
[target : attribute-list]
下表顯示可能的 target
值清單。
目標值 | 適用於 |
---|---|
assembly |
整個組件 |
module |
目前的組件模組 |
field |
類別或結構中的欄位 |
event |
事件 |
method |
方法或 get 和 set 屬性存取子 |
param |
方法參數或 set 屬性存取子參數 |
property |
屬性 |
return |
方法的傳回值、屬性索引子或 get 屬性存取子 |
type |
結構、類別、介面、列舉或委派 |
您可以指定field
屬性套用至支援欄位的目標值建立自動實作屬性。
下列範例示範如何將屬性套用到組件和模組。 如需詳細資訊,請參閱常見屬性 (C#)。
using System;
using System.Reflection;
[assembly: AssemblyTitleAttribute("Production assembly 4")]
[module: CLSCompliant(true)]
下列範例示範如何在 C# 中將屬性套用至方法、方法參數和方法傳回值。
// default: applies to method
[ValidatedContract]
int Method1() { return 0; }
// applies to method
[method: ValidatedContract]
int Method2() { return 0; }
// applies to parameter
int Method3([ValidatedContract] string contract) { return 0; }
// applies to return value
[return: ValidatedContract]
int Method4() { return 0; }
注意
不論 ValidatedContract
定義為有效的目標為何,都必須指定 return
目標,即使 ValidatedContract
已定義為只套用至傳回值也一樣。 換句話說,編譯器不會使用 AttributeUsage
資訊來解析模稜兩可的屬性目標。 如需詳細資訊,請參閱 AttributeUsage。
屬性的常見用法
下列清單包含一些程式碼中常見的屬性用法:
- 在 Web 服務中使用
WebMethod
屬性標示方法,以表示此方法應該可以透過 SOAP 通訊協定來呼叫。 如需詳細資訊,請參閱WebMethodAttribute。 - 描述在與原生程式碼交互作用時,如何封送處理方法參數。 如需詳細資訊,請參閱MarshalAsAttribute。
- 描述適用於類別、方法和介面的 COM 屬性。
- 使用 DllImportAttribute 類別呼叫 Unmanaged 程式碼。
- 針對標題、版本、描述或商標等方面來描述您的組件。
- 描述要將類別的哪些成員序列化以取得持續性。
- 描述如何基於 XML 序列化目的,在類別成員與 XML 節點之間進行對應。
- 描述方法的安全性需求。
- 指定用來強制執行安全性的特性。
- 控制由 Just-In-Time (JIT) 編譯器所進行的最佳化,讓程式碼保持易於偵錯。
- 取得有關方法之呼叫端的資訊。
反映概觀
反映在下列情況下十分有用:
- 當您需要存取程式中繼資料中的屬性時。 如需詳細資訊,請參閱擷取儲存於屬性中的資訊。
- 如需檢查和具現化組件中的類型。
- 若要在執行階段建置新型別。 使用 System.Reflection.Emit 中的類別。
- 對於執行晚期繫結,存取在執行階段建立的類型上的方法。 請參閱動態載入和使用型別一文。
相關章節
其他資訊: