C# の属性

 
属性 (Attribute) は、プログラムの実行時にさまざまな要素 (クラス、メソッド、構造体、列挙など) の動作情報を伝えるために使用される宣言コードです。コンパイラ指令、コメント、説明、メソッド、クラス情報などのメタデータは、属性を使用してプログラムに追加できます。 .Net Framework は、定義済み属性とカスタム属性という 2 種類の属性を提供します。

 

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

  • メタデータは、機能を使用してプログラムに追加できます。メタデータとは、プログラム内のさまざまな要素に関する情報を指します。すべての .NET プログラムには、指定されたメタデータのセットが含まれています。
  • 1 つ以上の属性をプログラム全体、モジュール、またはクラスや属性などの小さなプログラム要素に適用できます。
  • トレイトはメソッドやプロパティなどの引数を受け入れることができます。
  • プログラムはリフレクションを使用して、自身のメタデータや他のプログラムのメタデータを調べることができます。

1. 特徴を定義する

C# で属性を定義するための構文は次のとおりです。

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

このうち、 [ ]は機能の名前と値を定義するために使用され、positional_parametersは基本情報を指定するために使用され、name_parameterはオプション情報を指定するために使用されます。

2. 事前定義された機能

.Net Framework には、次の 3 つの事前定義プロパティが提供されています。

  • 属性の使用法。
  • 条件付き。
  • 廃止。

1) 属性の使用法

事前定義属性 AttributeUsage は、属性を適用できる項目タイプを定義するカスタム属性クラスの使用方法を記述するために使用されます。 AttributeUsage の構文は次のとおりです。

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

パラメータは次のように説明されます。

  • パラメータ validon は、属性を配置できる言語要素を定義するために使用されます。これは列挙子 AttributeTargets の値の組み合わせです。デフォルト値は AttributeTargets.All です。
  • パラメータallowmultiple (オプション・パラメータ)は、この機能のAllowMultiple属性(プロパティ)にブール値を提供するために使用されます。デフォルト値はfalse(1回のみ使用)です。trueの場合、機能は複数回使用されます。
  • パラメーター継承 (オプションのパラメーター) は、機能の Inherited 属性 (プロパティ) にブール値を提供するために使用されます。デフォルトは false (継承されません) で、true の場合、機能は派生クラスによって継承できます。

サンプルコードは次のとおりです。

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

2) 条件付き

事前定義属性 Conditional は、指定された前処理識別子に依存して実行されるメソッドをマークするために使用されます。この機能の値に応じて、コンパイル時にさまざまな効果が生じます。たとえば、値が Debug または Trace の場合、コードのデバッグ時に変数の値が表示されます。

事前定義属性 Conditional の構文形式は次のとおりです。

[Conditional(
    conditionalSymbol
)]

例えば:

[Conditional(“DEBUG”)]

[例] 次の例は、事前定義機能Conditionalの使用例を示しています。

 #define DEBUG
using System;
using System.Diagnostics;

namespace it-kiso.com
{
    class Demo
    {
        static void function1()
        {
            Myclass.Message("Function1 関数");
            function2();
        }
        static void function2()
        {
            Myclass.Message("Function2 関数");
        }
        static void Main(string[] args) 
        {
            Myclass.Message("Main 関数");
            function1();
            Console.ReadKey();
        }
    }
    public class Myclass
    {
        [Conditional("DEBUG")]
        public static void Message(string msg)
        {
            Console.WriteLine(msg);
        }
    }
} 

操作の結果は次のようになります。

Main 関数
Function1 関数
Function2 関数

3) 時代遅れ

事前定義された属性 Obsolete は、使用すべきではないプログラムをマークするために使用され、これを使用してオブジェクト要素を破棄するようにコンパイラーに通知できます。たとえば、クラス内の古いメソッドを新しいメソッドで置き換える必要がある場合、この機能を使用して古いメソッドを廃止 (廃止) としてマークし、新しいメソッドの代わりに新しいメソッドを使用するように求めるメッセージを出力できます。古い方法。

事前定義属性 Obsolete の構文形式は次のとおりです。

[Obsolete (
   message
)]

[Obsolete (
   message,
   iserror
)]

構文は次のように説明されます。

  • パラメータ メッセージは、項目が廃止された理由と、代わりに何を使用する必要があるかを説明する文字列です。
  • パラメータ iserror はブール値で、デフォルト値は false (コンパイラは警告を生成します) ですが、true に設定すると、コンパイラは項目をエラーとして扱います。

[例] 次の例は、事前定義属性 Obsolete の使用例を示しています。

 using System;

namespace it-kiso.com
{
    class Demo
    {
        [Obsolete("OldMethodは廃止されました。NewMethodを使用してください。", true)]
        static void OldMethod()
        {
          Console.WriteLine("既に廃止された関数");
        }
        static void NewMethod()
        {
          Console.WriteLine("新しく定義された関数");
        }
        static void Main(string[] args) 
        {
            OldMethod();
        }
    }
} 
3. カスタム機能

.Net Framework を使用すると、宣言情報を保存するだけでなく、実行時に取得できるカスタム属性を作成できます。カスタム属性の作成と使用は、次の 4 つの手順に分けることができます。

  • カスタム属性を宣言します。
  • カスタム機能を構築します。
  • ターゲット プログラムにカスタム機能を適用します。
  • リフレクション経由でプロパティにアクセスします。

最後のステップでは、さまざまなシンボルを見つけるためにメタデータを読み取る簡単なプログラムを作成します。メタデータはデータに関するデータ、または他のデータに関する情報を記述するために使用されます。プログラムは、実行時にプロパティにアクセスするためにリフレクションを使用する必要があります。

1) カスタム属性を宣言する

カスタム属性は、次のように System.Attribute クラスを拡張する必要があります。

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

public class DeBugInfo : System.Attribute

上記のサンプル コードでは、DeBugInfo というカスタム プロパティを宣言しました。

2) カスタム機能を構築する

以下にリストされているデバッグ情報を保存できる DeBugInfo というカスタム属性を構築しましょう。

  • バグのコード番号。
  • バグの開発者の名前。
  • コードが最後にレビューされた日付。
  • 開発者トークンを格納する文字列メッセージ。

DebugInfo クラスには、最初の 3 つの情報を保存するための 3 つのプライベート プロパティ (プロパティ) と、メッセージを保存するための 1 つのパブリック プロパティ (パブリック) があります。したがって、バグ番号、開発者名、およびレビュー日は DeBugInfo クラスの必須の位置パラメーターになりますが、メッセージはオプションの名前付きパラメーターになります。

各フィーチャには少なくとも 1 つのコンストラクターがあり、位置パラメーターはコンストラクターを介して渡す必要があります。次の例に示すように:

 // 自作の属性 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;
      }
  }
} 

3) カスタム プロパティを適用する

ターゲットの隣に機能を配置して機能を適用します。サンプル コードは次のとおりです。

use System;

namespace it-kiso.com;
{
    class Demo
    {
        static void Main(string[] args) 
        {
            Rectangle rec = new Rectangle(12, 15);
            rec.Display();
        }
    }

    [DeBugInfo(45, "Zara Ali", "12/8/2012", Message = "返却値の型が一致していない")]
    [DeBugInfo(49, "Nuha Ali", "10/10/2012", Message = "未使用の変数")]
    クラス 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 = "返却値の型が一致していない")]
        public double GetArea()
        {
            return length * width;
        }
        [DeBugInfo(56, "Zara Ali", "19/10/2012")]
        public void Display()
        {
            Console.WriteLine("Length: {0}", length);
            Console.WriteLine("Width: {0}", width);
            Console.WriteLine("Area: {0}", GetArea());
        }
    }
    // クラス及びそのメンバーに割り当てられたカスタム属性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;
            }
        }
    }
} 

操作の結果は次のようになります。

Length: 12
Width: 15
Area: 180

「 C# の属性」についてわかりやすく解説!絶対に観るべきベスト2動画

C# / .NET の属性 [C# 基本シリーズ、.NET 6 の例]