連載:[完全版]究極のC#プログラミング

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

川俣 晶
2009/12/14
Page1 Page2 Page3

10.3 アセンブリ間の名前競合の解決

 ここまで見てきた機能は、紛らわしい名前を的確に区別する手段といえる。実際には同じではない名前をうまく区別できない問題を解決する。

 しかし、最初から同じ名前が衝突するケースもある。もちろん、通常の開発時にはありえない事態である。名前が衝突したらコンパイルが通らないので、たいていはどちらかの名前を変更して回避する。だが、複数の既存のアセンブリを参照して開発を行う場合には修正できない名前の衝突が起こる可能性がある。たとえば、別個の組織から提供される別個のアセンブリが、たまたま同じ名前のクラスなどを定義してしまうことはありうるだろう。参照したアセンブリ間の名前の衝突は、それらのアセンブリがバイナリーファイルで提供されているとすれば、容易に解決することはできない。

 この問題に対処するために用意されたのが「externエイリアス」という機能である。

 まず、上記の理由により名前が衝突するケースを見てみよう。

 Visual Studio 2005で、コンソールアプリケーション1つとクラスライブラリ2つのプロジェクトを含むソリューションを作成する。コンソールアプリケーションからは、その2つのクラスライブラリのプロジェクトを参照しておく。

 図10.1のような感じである。

 個々のソースコードは、以下のリスト10.4リスト10.5リスト10.6のような内容になっている。


図10.1作成したソリューションの構成
Visual Studio 2008で、1つのコンソールアプリケーションプロジェクトと2つのクラスライブラリプロジェクトを含むソリューションを作成する。

using System;

namespace ClassLibrary
{
  public class Class
  {
    public static void SayHello()
    {
      Console.WriteLine("Hello in ClassLibrary1!");
    }
  }
}
リスト10.4 ClassLibrary1.Class1.cs

using System;

namespace ClassLibrary
{
  public class Class
  {
    public static void SayHello()
    {
      Console.WriteLine("Hello in ClassLibrary2!");
    }
  }
}
リスト10.5 ClassLibrary2.Class1.cs

using System;

class Program
{
  static void Main(string[] args)
  {
    ClassLibrary.Class.SayHello();
  }
}
リスト10.6 ConsoleApplication82.Program.cs

 ソリューションをビルドすると次のようなコンパイルエラーが出る。

エラー  1  型 'ClassLibrary.Class' は '……\ClassLibrary1.dll' および '……\ ClassLibrary2.dll の両方に存在します。
ソリューション(リスト10.4、5、6)のコンパイル結果

 この名前の衝突を、2つのクラスライブラリを修正することなく解決するには、次の3つの手順を必要とする。

参照にエイリアス名を設定する
externエイリアスの定義を追加する
externエイリアスを用いてメソッドを呼び出す

 まず、参照にエイリアス名を設定するには、ソリューションエクスプローラから参照しているアセンブリのプロパティを開く。図10.1の画面例では、[ConsoleApplication82]−[参照設定]の下の「ClassLibrary1」を右クリックし、メニューから[プロパティ]を選ぶ(図10.2参照)。


図10.2ClassLibrary1の参照プロパティ
コンソールアプリケーションで参照設定している「ClassLibrary1」を右クリックし、メニューから[プロパティ]を選んで表示する。

 ここで、[エイリアス]に「global」という名前が入っているが、これをアセンブリを参照するための別の名前に書き換える。参照するアセンブリごとに異なる名前を書き込んでおく。ここでは、「Lib1」という名前を指定しておこう。同様にして、ClassLibrary2については「Lib2」という名前を指定した。

 次に、externエイリアスの定義の追加である。これはソースコードの先頭にリスト10.7の2行を追加する。

extern alias Lib1;
extern alias Lib2;
リスト10.7 リスト10.6の先頭に追加するexternエイリアスの定義

 内容は簡単である。「extern alias」の後に、参照プロパティに書き込んだ名前を書くだけである。これで、ソースコード内でこの名前を参照する準備ができた。

 後は、externエイリアスを用いてメソッドを呼び出すだけである。

// リスト10.6のコード
ClassLibrary.Class.SayHello();

// externエイリアスを用いた呼び出し
Lib1.ClassLibrary.Class.SayHello(); // 出力:Hello in ClassLibrary1!
Lib2.ClassLibrary.Class.SayHello(); // 出力:Hello in ClassLibrary2!
externエイリアスを用いてメソッドを呼び出す

 または

// externエイリアスを用いた呼び出し(「::」を使用)
Lib1::ClassLibrary.Class.SayHello();
// 出力:Hello in ClassLibrary1!

Lib2::ClassLibrary.Class.SayHello();
// 出力:Hello in ClassLibrary2!
externエイリアスを用いてメソッドを呼び出す

 externエイリアスの後は「.」でもよいが、名前空間エイリアス修飾子(::)のほうが名前衝突のリスクが少ないので好ましいだろう。

 このように、アセンブリに付加したエイリアス名を含む名前を使ってアクセスすることで、まったく同じ名前が別個のアセンブリに含まれている場合でも、それらを区別して扱うことができる。

【Exercise】練習問題

 グローバル名前空間や名前空間エイリアス修飾子を使用しなければならない理由は何か? 正しいものを選べ。

  1. 名前空間を拡張するため
  2. 名前空間の別名を定義するため
  3. たまたま同じ名前が競合すると意図しないものが選ばれてしまうことがあるため
  4. 国際化(Globalization)を実現するため
  5. 異なるアセンブリを参照するため

 ◎解答:「3」(この行をマウスで選択してください)End of Article


 INDEX
  [完全版]究極のC#プログラミング
  Chapter10 名前空間のエイリアス修飾子と外部アセンブリ
    1.10.1 バージョンによるコード破壊
    2.10.2 グローバルな名前空間の強制
  3.10.3 アセンブリ間の名前競合の解決/練習問題
 
インデックス・ページヘ  「[完全版]究極のC#プログラミング」


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 記事ランキング

本日 月間