概要

  • 属性とはクラス、メソッドなど、プログラムのさまざまな構成要素(エンティティ)に情報を付加するのに使う仕組みである。
  • ソース上に記述可能。
  • 属性が示す情報は、リフレクションを利用して実行時に取得できる。
  • 定義済みの属性を使うことも、独自のカスタム属性を定義することもできる。
  • 属性を定義するとき、その名前には最後に"Attribute"を付ける慣例になっている。
    • 例:DllImportAttribute,ConditionalAttributeなど
  • ただしソース上で属性を使うときの記述では"Attribute"は省略できる(このことを知っておかないとSTAThreadをヘルプで引いてもSTAThreadAttributeしか出てこないので悩むことになる)
  • 属性はパラメータを持てる。
    • 名前付きパラメータとそうでないパラメータがあり、名前付きパラメータは省略可能。省略した場合は規定値が入力されたものとみなす。
  • 1 つの宣言で複数の属性を指定できる。その場合、個別に角かっこで囲むか、または同じ角かっこの中に入れる。
  • 一部の属性は、特定のエンティティに対して 2 回以上指定できる。
    例)
    [Conditional("DEBUG"), Conditional("TEST1")] 
    void TraceMethod() 
    {
      (略)
    }
  • 属性の定義はSystem.Attributeから派生した属性クラスを定義することで行う。つまり属性の実体はクラスによって実装されている。

新しい属性を作る例

namespace AttrTst 
{
	//クラスと構造体にしか付けられない属性であることを明記
	[AttributeUsage(AttributeTargets.Class|AttributeTargets.Struct)]
	public class AuthorAttribute : Attribute
	{
		public AuthorAttribute(string name) 
		{ 
			this.name = name; version = 1.0; 
		}
		public double version;
		string name;
	}

	[Author("カーネル",version=1.1)]
	public class cTst 
	{
		static void Main() 
		{
		}
	}
}

属性の取得

属性の情報はリフレクションを使って取得する。

using System;
using c = System.Console; // alias
namespace AttrTst 
{
	//クラスと構造体にしか付けられない属性であることを明記
	[AttributeUsage(AttributeTargets.Class|AttributeTargets.Struct)]
	public class AuthorAttribute : Attribute
	{
		public AuthorAttribute(string name) 
		{ 
			this.name = name; version = 1.0; 
		}
		double version;
		public double Version 
		{
			set{version = value;}
			get{return version;}
		}
		string name;
		public string Name 
		{
			get{return name;}
		}
	}

	[Author("カーネル",Version=1.1)]
	public class cTst 
	{
		static void Main() 
		{
			PrintAuthorInfo(typeof(cTst));
			c.ReadLine();
		}
		public static void PrintAuthorInfo(Type t) 
		{
			Console.WriteLine("Author information for {0}", t);
			Attribute[] attrs = Attribute.GetCustomAttributes(t);
			foreach(Attribute attr in attrs) 
			{
				if (attr is AuthorAttribute) 
				{
					AuthorAttribute a = (AuthorAttribute)attr;
					c.WriteLine("   {0}, version {1:f}",a.Name, a.Version);
				} 
				else 
				{
					c.WriteLine(attr.ToString());
				}
			}
		}
	}
}

実行結果

Author information for AttrTst.cTst
  カーネル, version 1.10

GetCustomAttributesがコールされたタイミングでAuthorAttributeクラスが生成される。

覚えておくと役立つかも知れない属性

Conditional属性

条件付でコンパイルするメソッドを定義できる。デバッグ時だけ呼ばれるメソッドとか。くわしくはヘルプ参照

Obsolete属性

定義のところで以下のように書いておくと

[Obsolete("古いモジュールのために残してあるだけなのでできるだけ使わないように。")]
public int a;

コンパイル時にワーニングが出るようになる。

warning CS0618: 'AttrTst.cTst.a' は古い形式です : '古いモジュールのために残してあるだけなのでできるだけ使わないように。'

StructLayout属性

マネージ メモリ内のクラスまたは構造体のデータ フィールドの物理的なレイアウトを制御。
Cで言うところの #pragma pack の代わりに使えそう。ただしクラスとか構造体単位。

/* C言語だとこのようになる構造体を渡したい場合
#define ALLOC_COUNT 128 
typedef struct tagTIME_INFO_EX{ 
  int YYYY; 
  int MM; 
  int DD; 
  int hh; 
  int mm; 
  int ss; 
  char str[ALLOC_COUNT]; 
} TIME_INFO_EX, *PTIME_INFO_EX;
*/

// C#ではこう書く
[StructLayout( LayoutKind.Sequential, Pack = 4 )] 
public struct TIME_INFO_EX 
{ 
    public int YYYY; 
    public int MM; 
    public int DD; 
    public int hh; 
    public int mm; 
    public int ss; 
    [MarshalAs( UnmanagedType.ByValArray, SizeConst = 128 )]
    public char[] str;  // C++: char str[128];
}

//呼び出す側
[DllImport( "myutil.dll", EntryPoint = "GetNowTimeStructEx" ) ] 
public static extern int GetNowTimeStructEx( out TIME_INFO_EX timeinfoEx ); 

TIME_INFO_EX timeinfoEx; 
GetNowTimeStructEx( out timeinfoEx );

DefaultEvent属性

  • 自作のコントロールをデザイナでダブルクリックしたときにコードと結びつくイベントを示す
    [DefaultEvent("Hoge")]
    public class MyControl : ..... {
      public event EventHandler Hoge;
    }

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2009-04-12 (日) 07:33:25 (4419d)