連載:C# 2.0入門

第7回 名前空間のエイリアス修飾子と外部アセンブリ

株式会社ピーデー 川俣 晶
2007/11/30
Page1 Page2 Page3

未来志向

 C# 2.0を学ぶC#プログラマーの皆さま、いかがお過ごしだろうか。

 のんびりと構えて連載を続けていたが、ふと気付けばすでに英語版Visual Studio 2008がリリースされてしまった。もちろん、これにはC# 3.0が含まれる。しかし、C# 3.0もこの連載で解説するC# 2.0の延長線上にあるものである。この連載で学んだ内容は、C# 3.0でも有効だ。この連載も今回を含め残り2回。それをクリアすると、次にC# 3.0への扉が開くのである。

 未来志向で1つ1つ積み上げながら行こう!

バージョンによるコード破壊

 プログラムをバージョンアップすると、何ら変更していないコードがコンパイル・エラーなどを起こす場合がある。新規に追加した名前が従来の名前と衝突して問題を起こすことがあるためだ。

 このような問題を回避するために、usingエイリアスで別名を定義し、その別名を経由して扱うという方法がある。usingエイリアスとは、「using A = B;」といった構文で記述する別名の定義で、この場合はAというキーワードを記述することで、実際にはBを使用することができる。

 しかし、このメカニズムは完全ではない。usingエイリアスがコード破壊を防げない例を以下に紹介する。

 まず、正常に動作するコードから示し、次にバージョンアップでコードが破壊される追加例を示す。なお、ここでは分かりやすさのために1本のソース・コードで全体を示すが、実際には複数のソース・コード、場合によっては複数のアセンブリに分散したコードが引き起こす問題であるといえる。

using System;
using A = NamespaceA; // エイリアスの定義
using B = NamespaceB; // エイリアスの定義

namespace NamespaceA
{
  public class ClassA
  {
    public static void SayHello()
    {
      Console.WriteLine("Hello from NamespaceA.ClassA");
    }
  }
}

namespace NamespaceB
{
  public class ClassA
  {
    public static void SayHello()
    {
      Console.WriteLine("Hello from NamespaceB.ClassA");
    }
  }
}

class Program
{
  static void Main(string[] args)
  {
    A.ClassA.SayHello(); // 出力:Hello from NamespaceA.ClassA
    B.ClassA.SayHello(); // 出力:Hello from NamespaceB.ClassA
  }
}
リスト1 正常に動作するコードの例

 このプログラムは、異なる名前空間に同じ名前のクラス(ClassA)が存在するが、より短いエイリアス名(AやB)を定義してそれを経由して区別している。

 さて、このプログラムに以下の1行を追加しよう。

namespace A {}
リスト2 コード破壊を引き起こす追加

 これにより「A.ClassA.SayHello();」の部分で次のようなコンパイル・エラーが発生する。

エラー  1  名前空間 '<グローバル名前空間>' は、エイリアス 'A' と競合する定義を含んでいます
リスト2をリスト1に追加した場合のコンパイル結果

 つまり、それまでエイリアス名であったAと同じ名前の名前空間を定義してしまったため、名前が競合してしまったのである。1本のソース・コード上であればすぐに気付いて名前を変えて回避するところだが、独立して開発されている別個のアセンブリ上で追加される名前空間名であれば、容易に名前を変更できないかもしれない。

 このようなケースで、問題を容易に解決するために、C# 2.0では「名前空間エイリアス修飾子」というものが追加されている。

 これを使用することで、名前の衝突という問題を「名前を変更することなく」解決できる。

// リスト1のコード
A.ClassA.SayHello();
B.ClassA.SayHello();

// 名前空間エイリアス修飾子(::)を使用
A::ClassA.SayHello();
B::ClassA.SayHello();
名前空間エイリアス修飾子を使う

 ここで使用された「::」が名前空間エイリアス修飾子である。

 名前空間エイリアス修飾子は、「.」と異なり、名前空間エイリアスにのみ適用される機能である。例えば、「A.……」と記述したとき、Aは名前空間名であったりクラス名であったり名前空間エイリアス名であったりする。しかし、「A::……」と記述すると、Aは名前空間エイリアスの名前のみを対象に探し出される。

 その結果として、Aという名前の名前空間名やクラス名がいくら存在したとしても、それは一切関係がなくなる。たとえ、プログラムのどこかでAという名前の名前空間が追加されたとしても、それによって影響を受けることはない。

 逆に、名前空間エイリアスの有効範囲は基本的に1本のソース・ファイル内になるので、「A::……」という記述で使われるAの定義は、必ず同じソース・ファイル内に存在することになる。それは、たいていの場合1人のプログラマーが自由に対処できる範囲内になるので、仮に名前の衝突という問題が起きても迅速に対処できるだろう。つまり名前空間エイリアス修飾子「::」はコード破壊に対する有力な対処方法ということになる。

グローバルな名前空間の強制

 ここまで見てきた使い方とは別に、名前空間エイリアス修飾子には、グローバルな名前空間を強制する使い方もある。これを用いないとうまくコンパイルできないケースがあるので、価値は大きい。コンパイルできないソース・コードが、これによってコンパイル可能になる事例を実際に見てみよう。

 以下は、コンパイルできない例である。

using System;

namespace A.B
{
  public class C
  {
    public static void SayHello()
    {
      Console.WriteLine("Hello!");
    }
  }
}

namespace Sample.A.B
{
  class C
  {
  }
}

namespace Sample.Main
{
  class Program
  {
    static void Main(string[] args)
    {
      A.B.C.SayHello();
      // 次のようなコンパイル・エラーとなる。
      // 'Sample.A.B.C' に 'SayHello' の定義がありません。
    }
  }
}
リスト3 コンパイルできない例

 コードを書いた側は、最上位の名前空間からすべて書いたのだからA.B.C.SayHello()は見つかるはずだと思うかもしれない。しかし、実際にはA.B.C.SayHello()はSample.A.B.C.SayHello()の省略形だとコンパイラに見なされてしまい、メソッドが見つからないというエラーになっている。

 これを解消するには、「global::」を補えばよい。

// リスト3のコード
A.B.C.SayHello();

// 「global::」を使用
global::A.B.C.SayHello(); // 出力:Hello!
グローバル名前空間から解釈することを強制する「global::」を使う

 「::」の手前の「global」は、その名前をグローバル名前空間(最上位の名前空間)から解釈することを強制する。これによって、紛らわしい名前空間名として解釈されることを防止できる。


 INDEX
  C# 2.0入門
  第7回 名前空間のエイリアス修飾子と外部アセンブリ
  1.未来志向/バージョンによるコード破壊/グローバルな名前空間の強制
    2.アセンブリ間の名前競合の解決
    3.アセンブリ内部へのアクセス/フレンド・アセンブリ/アクセスを制限する価値
 
インデックス・ページヘ  「C# 2.0入門」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間