屬性
屬性提供將元數據或宣告式資訊與程式代碼產生關聯的強大方法(元件、類型、方法、屬性等等)。 屬性與程式實體相關聯之後,可以使用稱為「反映」的技術,在運行時間查詢屬性。
屬性具有下列屬性:
- 屬性會將元數據新增至您的程式。 元數據 是程式中所定義類型的相關信息。 所有 .NET 元件都包含一組指定的元數據,描述元件中定義的類型和類型成員。 您可以新增自訂屬性,以指定所需的任何其他資訊。
- 您可以將一或多個屬性套用至整個元件、模組或較小的程序專案,例如類別和屬性。
- 屬性可以接受與方法和屬性相同的引數。
- 您的程式可以使用反映來檢查自己的元數據或其他程式中的元數據。
反射 提供描述組件、模組和類型的物件(類型為 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
在中繼語言中沒有意義,而且不會在反映 API 中使用。 IL 中的對應詞彙是 Family 和 Assembly。 若要使用反射識別 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
目標值,將屬性套用至針對自動實作屬性 建立的備份欄位。
下列範例示範如何將屬性套用至元件和模組。 如需詳細資訊,請參閱 Common Attributes (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 類別呼叫非受控代碼。
- 在標題、版本、描述或商標方面描述您的軟體組件。
- 指定類別中的哪些成員需要被序列化以便持久化。
- 描述如何對應類別成員與 XML 節點以進行 XML 序列化。
- 描述方法的安全性需求。
- 指定用於強化安全性的特徵。
- 藉由即時編譯器 (JIT) 控制優化,讓程式碼保持易於偵錯。
- 取得方法呼叫端的相關信息。
反思概述
反思在以下情況下很有用:
- 當您必須存取程式元資料中的屬性時。 如需詳細資訊,請參閱 擷取儲存在屬性中的資訊。
- 用於檢查和實例化組件中的類型。
- 用於在執行期間建立新的類型。 在 System.Reflection.Emit中使用類別。
- 若要執行晚期系結,請存取在執行期間建立的類型的方法。 請參閱 動態載入和使用類型一文。
相關區段
如需詳細資訊: