- 追加された行はこの色です。
- 削除された行はこの色です。
- C#の属性 へ行く。
#contents
*概要 [#yca3bf43]
-''属性''とはクラス、メソッドなど、プログラムのさまざまな構成要素(エンティティ)に情報を付加するのに使う仕組みである。
-ソース上に記述可能。
-属性が示す情報は、リフレクションを利用して実行時に取得できる。
-定義済みの属性を使うことも、独自のカスタム属性を定義することもできる。
-属性を定義するとき、その名前には最後に''"Attribute"''を付ける慣例になっている。
--例:''DllImportAttribute,ConditionalAttribute''など
-ただしソース上で属性を使うときの記述では''"Attribute"''は省略できる(このことを知っておかないと''STAThread''をヘルプで引いてもSTAThreadAttributeしか出てこないので悩むことになる)
-属性はパラメータを持てる。
--名前付きパラメータとそうでないパラメータがあり、名前付きパラメータは省略可能。省略した場合は規定値が入力されたものとみなす。
-1 つの宣言で複数の属性を指定できる。その場合、個別に角かっこで囲むか、または同じ角かっこの中に入れる。
-一部の属性は、特定のエンティティに対して 2 回以上指定できる。~
例)
[Conditional("DEBUG"), Conditional("TEST1")]
void TraceMethod()
{
(略)
}
-属性の定義はSystem.Attributeから派生した属性クラスを定義することで行う。つまり属性の実体はクラスによって実装されている。
*新しい属性を作る例 [#z04658b7]
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()
{
}
}
}
*属性の取得 [#d92179ad]
属性の情報はリフレクションを使って取得する。
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クラスが生成される。
*覚えておくと役立つかも知れない属性 [#zae80706]
**Conditional属性 [#n19f0c3e]
条件付でコンパイルするメソッドを定義できる。デバッグ時だけ呼ばれるメソッドとか。くわしくはヘルプ参照
**Obsolete属性 [#k2075e84]
定義のところで以下のように書いておくと
[Obsolete("古いモジュールのために残してあるだけなのでできるだけ使わないように。")]
public int a;
コンパイル時にワーニングが出るようになる。
warning CS0618: 'AttrTst.cTst.a' は古い形式です : '古いモジュールのために残してあるだけなのでできるだけ使わないように。'
**StructLayout属性 [#x5afa824]
マネージ メモリ内のクラスまたは構造体のデータ フィールドの物理的なレイアウトを制御。~
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属性 [#e762cf6d]
-自作のコントロールをデザイナでダブルクリックしたときにコードと結びつくイベントを示す
[DefaultEvent("Hoge")]
public class MyControl : ..... {
public event EventHandler Hoge;
}