.NETの属性とは何ですか?


206

.NETの属性とは何ですか。それらは何に適していますか。また、独自の属性を作成するにはどうすればよいですか。

回答:


146

メタデータ。オブジェクト/メソッド/プロパティに関するデータ。

たとえば、DisplayOrderという属性を宣言すると、UIに表示するプロパティの順序を簡単に制御できます。次に、それをクラスに追加し、属性を抽出してUI要素を適切に順序付けるGUIコンポーネントをいくつか作成します。

public class DisplayWrapper
{
    private UnderlyingClass underlyingObject;

    public DisplayWrapper(UnderlyingClass u)
    {
        underlyingObject = u;
    }

    [DisplayOrder(1)]
    public int SomeInt
    {
        get
        {
            return underlyingObject .SomeInt;
        }
    }

    [DisplayOrder(2)]
    public DateTime SomeDate
    {
        get
        {
            return underlyingObject .SomeDate;
        }
    }
}

これにより、カスタムGUIコンポーネントを操作するときに、SomeIntが常にSomeDateの前に表示されるようになります。

ただし、直接コーディング環境以外で最も一般的に使用されることがわかります。たとえば、Windowsデザイナーはそれらを広範囲に使用するため、カスタムメイドのオブジェクトを処理する方法を知っています。次のようにBrowsableAttributeを使用します。

[Browsable(false)]
public SomeCustomType DontShowThisInTheDesigner
{
    get{/*do something*/}
}

たとえば、設計時に[プロパティ]ウィンドウの使用可能なプロパティにこれをリストしないようにデザイナーに指示します。

あなたは可能性があり、また、そのようなReflection.Emitとして、あるいは実行時の操作(例えばポストシャープなど)プリコンパイル操作、コード生成のためにそれらを使用します。たとえば、コードが実行するすべての呼び出しを透過的にラップする、プロファイリング用のコードを少し書くことができます。特定のメソッドに配置する属性を介してタイミングを「オプトアウト」できます。

public void SomeProfilingMethod(MethodInfo targetMethod, object target, params object[] args)
{
    bool time = true;
    foreach (Attribute a in target.GetCustomAttributes())
    {
        if (a.GetType() is NoTimingAttribute)
        {
            time = false;
            break;
        }
    }
    if (time)
    {
        StopWatch stopWatch = new StopWatch();
        stopWatch.Start();
        targetMethod.Invoke(target, args);
        stopWatch.Stop();
        HandleTimingOutput(targetMethod, stopWatch.Duration);
    }
    else
    {
        targetMethod.Invoke(target, args);
    }
}

それらを宣言するのは簡単です。属性から継承するクラスを作成するだけです。

public class DisplayOrderAttribute : Attribute
{
    private int order;

    public DisplayOrderAttribute(int order)
    {
        this.order = order;
    }

    public int Order
    {
        get { return order; }
    }
}

また、属性を使用する場合、サフィックス「属性」を省略できることを覚えておいてください。コンパイラーが追加します。

注:属性はそれ自体では何も行いません属性を使用する他のコードが必要です。そのコードはあなたのために書かれていることもあれば、自分で書く必要があることもあります。たとえば、C#コンパイラは、フレームワークが一部を使用する特定のフレームワークに注意します(たとえば、NUnitは、クラスの[TestFixture]とアセンブリのロード時にテストメソッドの[Test]を探します)。
したがって、独自のカスタム属性を作成する場合は、コードの動作にまったく影響しないことに注意してください。(リフレクションを介して)属性をチェックし、それらに作用する他の部分を記述する必要があります。


32
価値があるのは、これはすべての(組み込み).NET属性のリストです:msdn.microsoft.com/en-us/library/aa311259
VS.71).aspx

1
「SomeProfilingMethod」を属性としてどのように使用しますか?
RayLoveless 2016年

@RayLovelessは属性ではありません。SomeProfilingMethodは、プロファイリング属性を探すインストルメンテーションコードです。特にこの例では、「オプトイン」属性ではなく、「オプトアウト」属性(NoTimingAttribute)を探すようにしています。アイデアは、すべての時間を計ることです。
2016年

@Quibblesomeを追加できますか?「属性はそれ自体では何もしません- 使用するには他のコードが必要です(コンパイラーはカップルを考慮し、異なるフレームワークはいくつかを使用します。属性を作成するだけではコードの動作に影響しません- (リフレクションを介して)属性をチェックし、それらに作用する他の部分を記述する必要があります。」(または、あなたが大丈夫なら私はそれをすることができます)。多くの人々は属性が魔法のように機能することを期待しており、ここでの答えのどれもそれを明確にしません。(または単にそれをカバーするstackoverflow.com/questions/4879521/…へのリンク)
Alexei Levenkov

Bingの使用を停止した場合のみ。いや。j / k私は主にBing iircを使用するプライマリとしてDuckDuckGoを使用しています。:)
2019

36

多くの人が答えましたが、今のところ誰もこれについて言及していません...

属性はリフレクションで頻繁に使用されます。反射はすでにかなり遅いです。

ランタイムパフォーマンスを向上させるために、カスタム属性をクラスとしてマークすることは非常に価値がありますsealed

また、このような属性を配置するのに適切な場所を検討し、属性(!)を属性として使用してこれをで示すこともお勧めしますAttributeUsage。使用可能な属性の使用法のリストは、驚くかもしれません。

  • アセンブリ
  • モジュール
  • クラス
  • ストラクト
  • 列挙型
  • コンストラクタ
  • 方法
  • 物件
  • フィールド
  • イベント
  • インターフェース
  • パラメータ
  • 委任
  • 戻り値
  • GenericParameter
  • すべて

AttributeUsage属性がAttributeUsage属性のシグネチャの一部であることもクールです。循環依存関係についておっと!

[AttributeUsageAttribute(AttributeTargets.Class, Inherited = true)]
public sealed class AttributeUsageAttribute : Attribute

13

属性は、クラスにタグを付けるための一種のメタデータです。これは、WinFormsでツールバーからコントロールを非表示にする場合などによく使用されますが、独自のアプリケーションに実装して、さまざまなクラスのインスタンスが特定の方法で動作できるようにすることができます。

まず、属性を作成します。

[AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=true)]
public class SortOrderAttribute : Attribute
{
    public int SortOrder { get; set; }

    public SortOrderAttribute(int sortOrder)
    {
        this.SortOrder = sortOrder;
    }
}

すべての属性クラスが有効であるためには、「属性」という接尾辞が必要です。
これが完了したら、属性を使用するクラスを作成します。

[SortOrder(23)]
public class MyClass
{
    public MyClass()
    {
    }
}

SortOrderAttribute次のようにして、特定のクラス(ある場合)を確認できます。

public class MyInvestigatorClass
{
    public void InvestigateTheAttribute()
    {
        // Get the type object for the class that is using
        // the attribute.
        Type type = typeof(MyClass);

        // Get all custom attributes for the type.
        object[] attributes = type.GetCustomAttributes(
            typeof(SortOrderAttribute), true);

        // Now let's make sure that we got at least one attribute.
        if (attributes != null && attributes.Length > 0)
        {
            // Get the first attribute in the list of custom attributes
            // that is of the type "SortOrderAttribute". This should only
            // be one since we said "AllowMultiple=false".
            SortOrderAttribute attribute = 
                attributes[0] as SortOrderAttribute;

            // Now we can get the sort order for the class "MyClass".
            int sortOrder = attribute.SortOrder;
        }
    }
}

これについてもっと読みたければ、かなり良い説明があるMSDNをいつでもチェックすることができます。
これがお役に立てば幸いです。


5

属性は、コード内のオブジェクトに適用できるいくつかの機能を含むクラスです。作成するには、System.Attributeから継承するクラスを作成します。

彼らにとって何が良いのかについては...彼らにはほとんど無限の用途があります。

http://www.codeproject.com/KB/cs/dotnetattributes.aspx


1
「機能性」はここでは間違った言葉です。それらはメタデータであり、機能ではありません
Marc Gravell

5

属性は、クラス、メソッド、またはアセンブリに適用されるメタデータのようなものです。

それらは、あらゆるものに適しています(デバッガーの視覚化、廃止としてマーク付け、シリアル化可能としてマーク付け、リストは無限です)。

独自のカスタムを作成するのは簡単です。ここから始める:

http://msdn.microsoft.com/en-us/library/sw480ze8(VS.71).aspx


5

私が現在取り組んでいるプロジェクトには、さまざまなフレーバーのUIオブジェクトのセットと、これらのオブジェクトを組み立ててメインアプリケーションで使用するページを作成するエディターがあり、DevStudioのフォームデザイナーのようです。これらのオブジェクトは独自のアセンブリに存在し、各オブジェクトは派生クラスUserControlであり、カスタム属性を持っています。この属性は次のように定義されています。

[AttributeUsage (AttributeTargets::Class)]
public ref class ControlDescriptionAttribute : Attribute
{
public:
  ControlDescriptionAttribute (String ^name, String ^description) :
    _name (name),
    _description (description)
  {
  }

  property String ^Name
  {
    String ^get () { return _name; }
  }

  property String ^Description
  {
    String ^get () { return _description; }
  }

private:
  String
    ^ _name,
    ^ _description;
};

そして私はそれをこのようなクラスに適用します:

[ControlDescription ("Pie Chart", "Displays a pie chart")]
public ref class PieControl sealed : UserControl
{
  // stuff
};

これは以前のポスターが言っていたものです。

属性を使用するために、エディターにはGeneric::List <Type>コントロールタイプを含むがあります。ユーザーがページにドラッグアンドドロップしてコントロールのインスタンスを作成できるリストボックスがあります。リストボックスを作成するにControlDescriptionAttributeは、コントロールのを取得し、リストのエントリに入力します。

// done for each control type
array <Object ^>
  // get all the custom attributes
  ^attributes = controltype->GetCustomAttributes (true);

Type
  // this is the one we're interested in
  ^attributetype = ECMMainPageDisplay::ControlDescriptionAttribute::typeid;

// iterate over the custom attributes
for each (Object ^attribute in attributes)
{
  if (attributetype->IsInstanceOfType (attribute))
  {
    ECMMainPageDisplay::ControlDescriptionAttribute
      ^description = safe_cast <ECMMainPageDisplay::ControlDescriptionAttribute ^> (attribute);

    // get the name and description and create an entry in the list
    ListViewItem
      ^item = gcnew ListViewItem (description->Name);

    item->Tag = controltype->Name;
    item->SubItems->Add (description->Description);

    mcontrols->Items->Add (item);
    break;
  }
}

注:上記はC ++ / CLIですが、C#に変換するのは難しくありません(そうですね、C ++ / CLIは嫌なものですが、私は:-()で作業する必要があります

ほとんどのものに属性を付けることができ、事前定義された属性の全範囲があります。上記のエディターは、プロパティとその編集方法を説明するプロパティのカスタム属性も探します。

全体のアイディアをつかんだら、それなしでどうやって生きてきたのか不思議に思うでしょう。


4

前述のように、属性は比較的簡単に作成できます。作業の他の部分は、それを使用するコードの作成です。ほとんどの場合、実行時にリフレクションを使用して、属性またはそのプロパティの存在に基づいて動作を変更します。コンパイルされたコードの属性を検査して、ある種の静的分析を行うシナリオもあります。たとえば、パラメーターが非nullとしてマークされ、分析ツールはこれをヒントとして使用できます。

属性を使用し、それらを使用するための適切なシナリオを知ることは、作業の大部分です。


3

属性は、基本的に、タイプ(クラス、メソッド、イベント、列挙型など)にアタッチするデータのビットです。

アイデアは、実行時に他のタイプ/フレームワーク/ツールが属性の情報についてタイプを照会しそれに基づいて動作するというものです。

したがって、たとえば、Visual Studioはサードパーティのコントロールの属性をクエリして、デザイン時にプロパティペインに表示する必要があるコントロールのプロパティを把握できます。

属性をアスペクト指向プログラミングで使用して、オブジェクトの装飾に使用する属性に基づいて実行時にオブジェクトを挿入/操作し、オブジェクトのビジネスロジックに影響を与えることなく、検証、ロギングなどをオブジェクトに追加することもできます。




弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.