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

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

川俣 晶
2009/12/14
Page1 Page2 Page3


 本記事は、(株)技術評論社が発行する書籍『[完全版]究極のC#プログラミング ― 新スタイルによる実践的コーディング』から、許可を得て転載しています。
 同書籍は、もともと本フォーラムにて連載していた『C# 2.0入門』、『C# 3.0入門』の記事を整理統合し、加筆、修正されたものです。

手元でまとめて読みたい方は、ぜひ書店などにてお買い求めください。

 【注意】本記事は、書籍の内容を改変することなく、そのまま転載したものです。このため用字用語の統一ルールなどは@ITのそれとは一致しません。あらかじめご了承ください。

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

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

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

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

 まず、正常に動作するコード(リスト10.1参照)から示し、次にバージョンアップでコードが破壊される追加例(リスト10.2参照)を示す。なお、ここではわかりやすさのために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
  }
}
リスト10.1 正常に動作するコードの例

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

本日 月間