不完全なnamespaceとusing
以下はusingの誤った使い方である。usingはnamespaceのデフォルトを指定するが、必ず完全なnamespaceでなければならない。つまり、namespaceのネストの一部だけを指定するものであってはならない。
1: using System;
2:
3: namespace Space1.Sub1
4: {
5: class Class2
6: {
7: public static void test()
8: {
9: Console.WriteLine("Space1.Sub1.Class2.test()");
10: }
11: }
12: }
13:
14: namespace ConsoleApplication23
15: {
16: using Space1;
17: class Class1
18: {
19: static void Main(string[] args)
20: {
21: Sub1.Class2.test(); // Sub1が見つからないというコンパイル・エラーになる
22: }
23: }
24: }
|
|
不完全なnamespaceを使用したサンプル・プログラム5 |
16行目では、Space1というnamespaceがデフォルトであると宣言している。この宣言そのものはエラーではない。なぜなら、Space1に属するクラスは宣言可能であるからだ。しかし、21行目の“Sub1.Class2.test();”という記述はエラーになる。なぜなら、Sub1はnamespace名の一部を成す名前であって、不完全なnamespace名を補うために16行目の宣言が使われることはないからだ。これをエラーなく機能するようにするなら、usingを使わずフルネームを書くか、あるいは、usingで完全なnamespace名(この場合はSpace1.Sub1)を指定する必要がある。
デフォルトnamespaceを指定するusingの複数使用
デフォルトnamespaceを指定するusingは、1つに限らず複数記述することができる。これにより、複数のクラス・ライブラリに含まれている多くのメソッドを、どれも短い名前で呼び出すことが可能になる。
しかし、何でもかんでもusingすればよいというものではない。例えば、usingで指定された複数のnamespace内に同じ名前のクラスがあり、それを呼び出そうとすると、コンパイラはエラーを発する。以下がその一例である。
1: using System;
2:
3: namespace Space1.Sub1
4: {
5: class Class2
6: {
7: public static void test()
8: {
9: Console.WriteLine("Space1.Sub1.Class2.test()");
10: }
11: }
12: }
13:
14: namespace Space2.Sub1
15: {
16: class Class2
17: {
18: public static void test()
19: {
20: Console.WriteLine("Space2.Sub1.Class2.test()");
21: }
22: }
23: }
24:
25: namespace ConsoleApplication23
26: {
27: using Space1.Sub1;
28: using Space2.Sub1;
29: class Class1
30: {
31: static void Main(string[] args)
32: {
33: Class2.test(); // Class2はあいまいな参照、というコンパイル・エラーになる
34: }
35: }
36: }
|
|
usingで指定された複数のnamespace内に同じ名前のクラスがあるサンプル・プログラム6 |
このサンプルソースには、3〜12行目で宣言される“Space1.Sub1”というnamespace、14〜23行目で宣言される“Space2.Sub1”というnamespace、(それに加えてMainメソッドを置くための“ConsoleApplication23”というnamespace)、がある。27〜28行目で、Space1.Sub1とSpace2.Sub1をusingで指定している、その結果、このブロック内にあるメソッドからは、この2つのnamespaceに属するメソッドは、namespace名抜きで自由に呼び出すことが可能になる。だが、この2つのnamespaceは同じClass2という名前を持ったクラスが存在する。そこで、このClass2を利用する33行目のようなコードを記述すると、コンパイラは「あいまいな参照」というエラーを出す。これは、正当な指定先候補が複数発見でき、その中でどれが適切なのかコンパイラには判断できなかったことを示す。
このエラーを解決するには、本当に呼び出したいクラスはどれなのか、namespace名を明示してはっきりさせる必要がある。そのような手順が煩雑に感じられるようなら、別名を宣言するusingの機能を用いて、特定のクラスについて短い名前を宣言して使うとよいだろう。以下は実際にそのように記述した例である。
1: using System;
2:
3: namespace Space1.Sub1
4: {
5: class Class2
6: {
7: public static void test()
8: {
9: Console.WriteLine("Space1.Sub1.Class2.test()");
10: }
11: }
12: }
13:
14: namespace Space2.Sub1
15: {
16: class Class2
17: {
18: public static void test()
19: {
20: Console.WriteLine("Space2.Sub1.Class2.test()");
21: }
22: }
23: }
24:
25: namespace ConsoleApplication23
26: {
27: using Space1.Sub1;
28: using Space2.Sub1;
29: using MyClass2 = Space1.Sub1.Class2;
30: class Class1
31: {
32: static void Main(string[] args)
33: {
34: MyClass2.test();
35: }
36: }
37: }
|
|
サンプル・プログラム6を改良したサンプル・プログラム7 |
これを実行した結果は以下のようになる。
|
サンプル・プログラム7の実行結果 |
2つの異なるnamespaceにある同じ名前のクラスの片方に別名をつけることにより、アクセスするクラスを特定する。
|
ここでは29行目の別名を定義するusingと、34行目でその別名を経由して呼び出している部分に注目していただきたい。
まとめ
namespaceやusingの機能は、短いプログラムを書いているときにはありがたみを感じられないかもしれない。しかし、膨大なクラス・ライブラリを活用するために、usingの機能は不可欠である。また、そのようなライブラリを整備するためには、namespaceは必須の機能と言える。今、この2つの機能がピンと来ないとしても、開発の現場で本格的な開発プロジェクトに携わるようになれば、「ああ、あってよかった」と思う機会が訪れるだろう。そのときのために、頭の片隅にでも知識を入れておくとよいだろう。
次回はいまいちどクラスに戻り、詳細を解説してみたいと考えている。
それでは次回もLet's See Sharp!
Insider.NET 記事ランキング
本日
月間