回答:
メタデータ。オブジェクト/メソッド/プロパティに関するデータ。
たとえば、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]を探します)。
したがって、独自のカスタム属性を作成する場合は、コードの動作にまったく影響しないことに注意してください。(リフレクションを介して)属性をチェックし、それらに作用する他の部分を記述する必要があります。
多くの人が答えましたが、今のところ誰もこれについて言及していません...
属性はリフレクションで頻繁に使用されます。反射はすでにかなり遅いです。
ランタイムパフォーマンスを向上させるために、カスタム属性をクラスとしてマークすることは非常に価値がありますsealed
。
また、このような属性を配置するのに適切な場所を検討し、属性(!)を属性として使用してこれをで示すこともお勧めしますAttributeUsage
。使用可能な属性の使用法のリストは、驚くかもしれません。
AttributeUsage属性がAttributeUsage属性のシグネチャの一部であることもクールです。循環依存関係についておっと!
[AttributeUsageAttribute(AttributeTargets.Class, Inherited = true)]
public sealed class AttributeUsageAttribute : Attribute
属性は、クラスにタグを付けるための一種のメタデータです。これは、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をいつでもチェックすることができます。
これがお役に立てば幸いです。
属性は、コード内のオブジェクトに適用できるいくつかの機能を含むクラスです。作成するには、System.Attributeから継承するクラスを作成します。
彼らにとって何が良いのかについては...彼らにはほとんど無限の用途があります。
属性は、クラス、メソッド、またはアセンブリに適用されるメタデータのようなものです。
それらは、あらゆるものに適しています(デバッガーの視覚化、廃止としてマーク付け、シリアル化可能としてマーク付け、リストは無限です)。
独自のカスタムを作成するのは簡単です。ここから始める:
http://msdn.microsoft.com/en-us/library/sw480ze8(VS.71).aspx
私が現在取り組んでいるプロジェクトには、さまざまなフレーバーの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は嫌なものですが、私は:-()で作業する必要があります
ほとんどのものに属性を付けることができ、事前定義された属性の全範囲があります。上記のエディターは、プロパティとその編集方法を説明するプロパティのカスタム属性も探します。
全体のアイディアをつかんだら、それなしでどうやって生きてきたのか不思議に思うでしょう。
前述のように、属性は比較的簡単に作成できます。作業の他の部分は、それを使用するコードの作成です。ほとんどの場合、実行時にリフレクションを使用して、属性またはそのプロパティの存在に基づいて動作を変更します。コンパイルされたコードの属性を検査して、ある種の静的分析を行うシナリオもあります。たとえば、パラメーターが非nullとしてマークされ、分析ツールはこれをヒントとして使用できます。
属性を使用し、それらを使用するための適切なシナリオを知ることは、作業の大部分です。
属性は、基本的に、タイプ(クラス、メソッド、イベント、列挙型など)にアタッチするデータのビットです。
アイデアは、実行時に他のタイプ/フレームワーク/ツールが属性の情報についてタイプを照会し、それに基づいて動作するというものです。
したがって、たとえば、Visual Studioはサードパーティのコントロールの属性をクエリして、デザイン時にプロパティペインに表示する必要があるコントロールのプロパティを把握できます。
属性をアスペクト指向プログラミングで使用して、オブジェクトの装飾に使用する属性に基づいて実行時にオブジェクトを挿入/操作し、オブジェクトのビジネスロジックに影響を与えることなく、検証、ロギングなどをオブジェクトに追加することもできます。
カスタム属性をサブクラスでタグ値を定義する簡単な方法として使用して、サブクラスごとに同じコードを何度も書く必要がありません。独自のコードでカスタム属性を定義して使用する方法について、John Watersが簡潔で簡潔な例を見つけました。
http://msdn.microsoft.com/en-us/library/aa288454(VS.71).aspxにチュートリアルがあります
属性の作成を開始するには、C#ソースファイルを開き、attribute
[TAB]を入力してヒットします。新しい属性のテンプレートに展開されます。