English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

C# 特性(Attribute)

特性(Attribute)は、実行時でプログラムのさまざまな要素(例えばクラス、メソッド、構造体、エnum、コンポーネントなど)の動作情報を伝達する宣言的なタグです。特性を使用して、プログラムに宣言的な情報を追加できます。宣言的なタグは、適用する要素の前に配置される括弧([ ])で説明されます。

特性(Attribute)はメタデータを追加するために使用され、コンパイラ命令やコメント、説明、メソッド、クラスなどの他の情報を含みます。.Net フレームワークは、2つの種類の特性を提供しています:プリ定义特性和カスタム特性。

指定特性(Attribute)

指定特性(Attribute)の構文は以下の通りです:

[attribute(positional_parameters, name_parameter = value, ...)]
element

特性(Attribute)の名前と値は括弧内で指定され、適用する要素の前に配置されます。positional_parameters は必須の情報を指定し、name_parameter はオプションの情報を指定します。

プリ定义特性(Attribute)

.Net フレームワークは、3つのプリ定义特性を提供しています:

  • AttributeUsage

  • Conditional

  • Obsolete

AttributeUsage

プリ定义特性 AttributeUsage カスタム特性クラスの使用方法を説明します。これにより、特性が適用できるプロジェクトのタイプが指定されます。

この特性の記法は以下の通りです:

[AttributeUsage(
   validon,
   AllowMultiple=allowmultiple,
   Inherited=inherited
)]

その中で:

  • パラメータ validon は、特性が配置できる言語要素を指定します。これはエンリーチャー AttributeTargets の値の組み合わせ。デフォルト値は AttributeTargets.All

  • パラメータ allowmultiple(オプション)この特性の AllowMultiple 属性(property)は布尔値を提供します。true なら、この特性は複数使用できます。デフォルト値は false(単一使用のみです)。

  • パラメータ inherited(オプション)この特性の Inherited 属性(property)は布尔値を提供します。true なら、この特性は派生クラスに継承されます。デフォルト値は false(継承されません)。

例えば:

[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property, 
AllowMultiple = true)]

Conditional

このプレデファイン特性は、指定されたプレプロセッサ識別子に依存する条件メソッドをマークします。

指定された値に応じてメソッド呼び出しの条件コンパイルが引き起こされます。 Debug または Trace例えば、デバッグコード中に変数の値を表示します。

この特性の記法は以下の通りです:

[Conditional(
   conditionalSymbol
)]

例えば:

[Conditional("DEBUG")]

以下の例がこの特性を示しています:

#define DEBUG
using System;
using System.Diagnostics;
public class Myclass
{
    [Conditional("DEBUG")]
    public static void Message(string msg)
    {
        Console.WriteLine(msg);
    }
}
class Test
{
    static void function1();
    {
        Myclass.Message("Function 1.');
        function2();
    }
    static void function2();
    {
        Myclass.Message("Function 2.');
    }
    public static void Main()
    {
        Myclass.Message("Main function.");
        function1();
        Console.ReadKey();
    }
}

上記のコードがコンパイルおよび実行された場合、以下の結果が得られます:

Main function
Function 1
Function 2

Obsolete

このプレデファイン特性は、使用すべきでないプログラムエンティティをマークします。特定のターゲット要素をコンパイラが捨てることができるように通知することができます。例えば、新しいメソッドがクラスに使用されているが、古いメソッドをクラス内に保持したい場合、新しいメソッドを使用するべきというメッセージを表示して、それを obsolete(廃止)としてマークすることができます。

この特性の記法は以下の通りです:

[Obsolete(
   message
)]
[Obsolete(
   message,
   iserror
)]

その中で:

  • パラメータ messageこれは、プロジェクトがなぜ廃止されたか、どのように代替すべきかを説明する文字列です。

  • パラメータ iserrorこれは布尔値です。この値が true なら、コンパイラはそのプロジェクトの使用をエラーとして扱わなければなりません。デフォルト値は false(コンパイラは警告を出力します)。

以下の例がこの特性を示しています:

using System;
public class MyClass
{
   [Obsolete("Don't use OldMethod, use NewMethod instead", true)]
   static void OldMethod()
   { 
      Console.WriteLine("It is the old method");
   }
   static void NewMethod()
   { 
      Console.WriteLine("It is the new method"); 
   }
   public static void Main()
   {
      OldMethod();
   }
}

このプログラムをコンパイルしようとすると、コンパイラは以下のようなエラーメッセージを出します:

 OldMethodを使用しないで、代わりにNewMethodを使用してください

カスタム特性(Attribute)

.Net フレームワークは、宣言的な情報を保存し、実行時に検索できるカスタム特性を作成することができます。この情報は、設計基準およびアプリケーションの要件に応じて、どのターゲット要素とも関連付けることができます。

カスタム特性の作成および使用には、以下の4つのステップがあります:

  • カスタム特性の宣言

  • カスタム特性の構築

  • ターゲットプログラム要素にカスタム特性を適用

  • 反映を通じて特性にアクセス

最後のステップは、メタデータを読み取る簡単なプログラムを書くことで、メタデータは他のデータを記述するデータと情報です。このプログラムは、反映を通じて実行時に特性にアクセスする必要があります。これについて、次の章で詳しく説明します。

カスタム特性の宣言

新しいカスタム特性は、 System.Attribute クラスを宣言しました。例えば:

// 一个自定义特性 BugFix 被赋给类及其成员
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]
public class DeBugInfo : System.Attribute

上記のコードでは、 DeBugInfo のカスタム特性を構築します。

カスタム特性の構築

以下に、 DeBugInfo のカスタム特性は、デバッグプログラムが取得した情報を保存します。以下の情報を保存します:

  • バグのコード番号

  • このバグを特定した開発者名

  • このコードを最後にレビューした日付

  • 開発者マークを含む文字列メッセージを保存する

私たちの DeBugInfo クラスは、前3つの情報を保存するために3つのプライベート属性(property)を持ち、メッセージを保存するためにパブリック属性(property)を持ちます。したがって、バグ番号、開発者名、レビュー日付は DeBugInfo クラスの必需の定位( positional)パラメータであり、メッセージはオプションの名前(named)パラメータです。

各特性必须至少有一个构造函数。必需的定位( positional)参数应通过构造関数で伝達されます。以下のコードがその例です。 DeBugInfo 类:

// 一个自定义特性 BugFix 被赋给类及其成员
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]
public class DeBugInfo : System.Attribute
{
  private int bugNo;
  private string developer;
  private string lastReview;
  public string message;
  public DeBugInfo(int bg, string dev, string d)
  {
      this.bugNo = bg;
      this.developer = dev;
      this.lastReview = d;
  }
  public int BugNo
  {
      get
      {
          return bugNo;
      }
  }
  public string Developer
  {
      get
      {
          return developer;
      }
  }
  public string LastReview
  {
      get
      {
          return lastReview;
      }
  }
  public string Message
  {
      get
      {
          return message;
      }
      set
      {
          message = value;
      }
  }
}

应用自定义特性

通过把特性放置在紧接着它的目标之前,来应用该特性:

[DeBugInfo(45, "Zara Ali", "12/8/2012", Message = "Return type mismatch")]
[DeBugInfo(49, "Nuha Ali", \10/10/2012", Message = "Unused variable")]
class Rectangle
{
  // 成员变量
  protected double length;
  protected double width;
  public Rectangle(double l, double w)
  {
      length = l;
      width = w;
  }
  [DeBugInfo(55, "Zara Ali", "19/10/2012",
  Message = "Return type mismatch")]
  public double GetArea()
  {
      return length * width;
  }
  [DeBugInfo(56, "Zara Ali", "19/10/2012])]
  public void Display()
  {
      Console.WriteLine("長さ: {0}", length);
      Console.WriteLine("幅: {0}", width);
      Console.WriteLine("面積: {0}", GetArea());
  }
}

次の章では、Reflection クラスオブジェクトを使用してこれらの情報を取得します。