共用方式為


屬性

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

屬性具有下列屬性:

  • 屬性會將元數據新增至您的程式。 元數據 是程式中所定義類型的相關信息。 所有 .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# 關鍵詞 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 類別庫中屬性的實際名稱。

屬性參數

許多屬性都有參數,可以是位置、未命名或具名。 任何位置參數都必須以特定順序指定,且無法省略。 具名參數是選擇性的,可以依任何順序指定。 會先指定位置參數。 例如,這三個屬性相等:

[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 目標值,將屬性套用至針對自動實作屬性 建立的備份欄位。

下列範例示範如何將屬性套用至元件和模組。 如需詳細資訊,請參閱 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) 控制優化,讓程式碼保持易於偵錯。
  • 取得方法呼叫端的相關信息。

反思概述

反思在以下情況下很有用:

如需詳細資訊: