名前付き引数
上の例では「AllowMultiple = true」という一風変わった引数を使用した。このような引数はコンストラクタの引数としては用意できない形式である。自作の属性で、このような引数を実現するには、コンストラクタの引数とは違う方法を使わねばならない。コンストラクタの引数は「ポジショナル引数(Positional Parameter)」、「AllowMultiple = true」のような方法は「名前付き引数(Named Parameter)」という。以下は「名前付き引数」を使用したサンプル・ソースである。
1: using System;
2: using System.Reflection;
3:
4: namespace ConsoleApplication19
5: {
6: [AttributeUsage(AttributeTargets.Class)]
7: class AuthorAttribute : Attribute
8: {
9: private string _name;
10: private string _organization;
11: public AuthorAttribute( string name )
12: {
13: _name = name;
14: _organization = "(no organization)";
15: }
16: public string name
17: {
18: get { return _name; }
19: }
20: public string organization
21: {
22: get { return _organization; }
23: set { _organization = value; }
24: }
25: }
26: [Author("Ichiro", organization="The Program Company")]
27: class Sample1
28: {
29: }
30: [Author("Jiro")]
31: class Sample2
32: {
33: }
34: [Author("Saburo", organization="The Software Group")]
35: class Class1
36: {
37: public static void dumpAuthor( string className )
38: {
39: Type type = Type.GetType("ConsoleApplication19." + className);
40: object [] list = type.GetCustomAttributes(typeof(AuthorAttribute),false);
41: foreach( AuthorAttribute item in list )
42: {
43: Console.WriteLine( "class {0} is written by {1} in {2}.", className, item.name, item.organization );
44: }
45: }
46: static void Main(string[] args)
47: {
48: dumpAuthor( "Sample1" );
49: dumpAuthor( "Sample2" );
50: dumpAuthor( "Class1" );
51: }
52: }
53: } |
|
「名前付き引数」を使用したサンプル・プログラム5 |
名前付き引数(Named Parameter)は等号を用いて指定し、省略可能である。属性の定義では、これをプロパティとして実装する。 |
これを実行すると以下のようになる。
|
サンプル・プログラム5の実行結果 |
所属組織を指定するための引数を省略した場合には、変数のデフォルト値である“(no organization)”となる。
|
ここでは、Author属性に、新しく“所属組織(organization)”という項目を付け加えてみた。26、34行目では「organization="組織名"」という書式で所属組織の名前が指定されている。しかし、30行目では指定されていない。名前付き引数は、省略も自由にできることを意味している。さて、一見、このソースには、名前付き引数を処理するコードがどこにもないように見えるかもしれない。実は、organizationという名前の名前付き引数をサポートするには、organizationという名前のpublicなプロパティを用意するだけでよいのである。つまり、20〜24行目のプロパティの存在が、organizationという名前付き引数の利用を可能としたわけである。そこからすぐに分かるとおり、名前付き引数が指定されなかった場合のデフォルト値は、そのクラス内で自由に用意することができる。ここでは14行目が、それを用意している。
2つの利用可能な属性名
属性名は、属性クラスの名前から最後の“Attribute”の部分を除いた名前を使用するのが普通だが、除かない名前を使用することもできる。以下はそれを示した例である。
1: using System;
2: using System.Reflection;
3:
4: namespace ConsoleApplication20
5: {
6: [AttributeUsage(AttributeTargets.Class)]
7: class SampleAttribute : Attribute
8: {
9: public SampleAttribute()
10: {
11: }
12: }
13: [Sample]
14: class Sample1
15: {
16: }
17: [SampleAttribute]
18: class Sample2
19: {
20: }
21: class Class1
22: {
23: public static void dumpAuthor( string className )
24: {
25: Type type = Type.GetType("ConsoleApplication20." + className);
26: object [] list = type.GetCustomAttributes(typeof(SampleAttribute),false);
27: if( list.Length > 0 )
28: {
29: Console.WriteLine( "class {0} has SampleAttribute attribute.", className );
30: }
31: }
32: static void Main(string[] args)
33: {
34: dumpAuthor( "Sample1" );
35: dumpAuthor( "Sample2" );
36: dumpAuthor( "Class1" );
37: }
38: }
39: } |
|
2つの属性名を使用したサンプル・プログラム6 |
属性名には、属性クラスの名前の最後にある“Attribute”を省略することができる。 |
これを実行すると以下のようになる。
|
サンプル・プログラム6の実行結果 |
属性[Sample]と[SampleAttribute]は同じ働きをしていることが分かる。
|
このソースでは、13行目と17行目で、それぞれAttributeを含む名前と含まない名前を記述している。しかし、26行目からSampleAttributeクラスの属性を調べれば、両方がSampleAttributeクラスとして認識されていることが分かるだろう。
余談だが、36行目ではClass1クラスを指定しているが、このクラスにはいかなる名前でもSampleAttributeクラスの属性は付いていないので、これに対応する表示は何も出ない。27行目でlist.Lengthが0になるためだ。
Insider.NET 記事ランキング
本日
月間