次の方法で共有


属性

属性は、メタデータまたは宣言型情報をコード (アセンブリ、型、メソッド、プロパティなど) と関連付けするための強力なメソッドを提供します。 属性をプログラム要素に関連付けると、リフレクションと呼ばれる手法を使用して、実行時にその属性を照会することができます。

属性には、次のプロパティがあります。

  • 属性は、プログラムにメタデータを追加します。 メタデータ は、プログラムで定義されている型に関する情報です。 すべての .NET アセンブリには、アセンブリで定義されている型と型メンバーを記述するメタデータの指定されたセットが含まれています。 カスタム属性を追加して、必要な追加情報を指定できます。
  • アセンブリ全体、モジュール、またはクラスやプロパティなどの小さなプログラム要素に 1 つ以上の属性を適用できます。
  • 属性は、メソッドやプロパティと同じ方法で引数を受け取ることができます。
  • プログラムでは、リフレクションを使用して、独自のメタデータまたは他のプログラムのメタデータを調べることができます。

リフレクション は、アセンブリ、モジュール、および型を記述する (Type型の) オブジェクトを提供します。 リフレクションを使用すると、型のインスタンスを動的に作成したり、型を既存のオブジェクトにバインドしたり、既存のオブジェクトから型を取得したり、メソッドを呼び出したり、そのフィールドとプロパティにアクセスしたりできます。 コードで属性を使用している場合は、リフレクションを使用してそれらにアクセスできます。 詳細については、「属性の」を参照してください。

すべての型がObject基底クラスから継承するGetType()メソッドを使用したリフレクションの簡単な例を示します。これにより、変数の型を取得します。

手記

.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 は中間言語 (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) { }

一部の属性は、特定のエンティティに対して複数回指定できます。 このような multiuse 属性の例は、ConditionalAttributeです。

[Conditional("DEBUG"), Conditional("TEST1")]
void TraceMethod()
{
    // ...
}

手記

慣例により、すべての属性名は "Attribute" という単語で終わり、.NET ライブラリ内の他の項目と区別されます。 ただし、コードで属性を使用する場合は、属性サフィックスを指定する必要はありません。 たとえば、[DllImport][DllImportAttribute]と同じですが、DllImportAttribute は .NET クラス ライブラリの属性の実際の名前です。

属性パラメーター

多くの属性にはパラメーターがあり、位置指定、名前なし、または名前付きにすることができます。 位置指定パラメーターは、特定の順序で指定する必要があり、省略できません。 名前付きパラメーターは省略可能であり、任意の順序で指定できます。 位置指定パラメーターは、最初に指定されます。 たとえば、次の 3 つの属性は同等です。

[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 が有効であると定義されているターゲットに関係なく、戻り値のみに適用するように ValidatedContract 定義されている場合でも、return ターゲットを指定する必要があります。 つまり、コンパイラはあいまいな属性ターゲットを解決するために AttributeUsage 情報を使用しません。 詳細については、「AttributeUsage」を参照してください。

属性の一般的な用途

次の一覧には、コードでの属性の一般的な使用方法をいくつか示します。

  • Web サービスの WebMethod 属性を使用してメソッドをマーキングし、SOAP プロトコル経由でメソッドを呼び出し可能にすることを示します。 詳細については、WebMethodAttributeを参照してください。
  • ネイティブ コードと相互運用するときにメソッド パラメーターをマーシャリングする方法について説明します。 詳細については、MarshalAsAttributeを参照してください。
  • クラス、メソッド、インターフェイスの COM プロパティについて説明します。
  • DllImportAttribute クラスを使用してアンマネージ コードを呼び出す。
  • タイトル、バージョン、説明、または商標の観点からアセンブリを記述する。
  • 永続化のためにシリアル化するクラスのメンバーを記述する。
  • XML シリアル化のためにクラス メンバーと XML ノード間でマップする方法について説明します。
  • メソッドのセキュリティ要件について説明します。
  • セキュリティの適用に使用される特性の指定。
  • Just-In-Time (JIT) コンパイラによる最適化の制御により、コードのデバッグが容易になります。
  • メソッドへの呼び出し元に関する情報の取得。

リフレクションの概要

リフレクションは、次の状況で役立ちます。

  • プログラムのメタデータ内の属性にアクセスする必要がある場合。 詳細については、「属性に格納されている情報の取得」を参照してください。
  • アセンブリ内の型を調べてインスタンス化する場合。
  • 実行時に新しい型を構築する場合。 System.Reflection.Emitでクラスを使用します。
  • 遅延バインディングを実行する場合は、実行時に作成された型のメソッドにアクセスします。 記事 「型を動的に読み込んで使用する方法」を参照してください。

詳細については、以下を参照してください。