共用方式為


屬性

屬性提供將元數據或宣告式資訊與程式代碼產生關聯的強大方式(元件、類型、方法、屬性等等)。 將屬性與程式實體產生關聯之後,您可以使用稱為「反映」的技術,在運行時間查詢屬性。

屬性具有下列屬性:

  • 屬性會將元數據新增至您的程式。 元數據 是程式中所定義類型的相關信息。 所有 .NET 元件都包含一組指定的元數據,描述元件中定義的類型和類型成員。 您可以新增自訂屬性來指定任何其他必要資訊。
  • 屬性可以套用至整個元件、模組或較小的程序專案,例如類別和屬性。
  • 屬性可以接受與方法和屬性相同的引數。
  • 屬性可讓程式使用反射,檢查其自身的元數據或其他程式中的元數據。

與反思一起工作

反射 提供的 API Type 描述元件、模組和類型。 您可以使用反映來動態建立類型的實例、將類型系結至現有的物件,或從現有的物件取得類型,以及叫用其方法或存取其字段和屬性。 當您在程式代碼中使用屬性時,反映可讓您存取它們。 如需詳細資訊,請參閱 屬性

以下是使用 GetType() 方法的簡單反映範例。 Object 基類中的所有類型都會繼承這個方法,用來取得變數的類型:

注意

請務必在 C# (.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

IL 的關鍵詞差異

C# 關鍵詞 protectedinternal 在中繼語言中沒有意義,而且不會在反映 API 中使用。 IL 中的對應詞彙是 FamilyAssembly。 以下是一些您可以使用這些詞彙的方式:

  • 若要使用反映來識別 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 類別庫中類別的實際名稱。

屬性參數

許多屬性都有參數,這些參數可以 位置未命名,或名為 。 下表說明如何操作具名屬性與位置屬性:

位置參數

屬性建構函式的參數:

具名參數

屬性的屬性或欄位:

  • 必須指定,不能省略
  • 永遠先指定
  • 特定 順序指定
  • 一律為選擇性,若為 false,請省略
  • 指定位置參數之後
  • 依任何順序指定

例如,下列程式代碼顯示三個對等 DllImport 屬性:

[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 方法或 getset 屬性存取子
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

檢視使用屬性的方式

以下是在程式代碼中使用屬性的一些常見方式:

  • 使用 HttpPost 屬性標記回應 POST 訊息的控制器方法。 如需詳細資訊,請參閱 HttpPostAttribute 類別。
  • 描述如何在與本機程式碼互通時封送方法參數。 如需詳細資訊,請參閱 MarshalAsAttribute 類別。
  • 描述類別、方法和介面的元件物件模型 (COM) 屬性。
  • 使用 DllImportAttribute 類別呼叫非受管程式碼。
  • 在標題、版本、描述或商標方面描述您的組件。
  • 描述要序列化以進行持續化的類別成員。
  • 描述如何在 XML 序列化中對應類別成員與 XML 節點。
  • 描述方法的安全性需求。
  • 指定用來強制執行安全性的特性。
  • 使用即時編譯器(JIT)控制優化,讓程式碼保持容易除錯。
  • 取得方法呼叫端的相關信息。

檢閱反思情境

反思在下列情況中很有用: