名前空間

名前空間とは

例えばコンソール画面に文字列を表示するためにはConsole.WriteLineメソッドを使用します。
この指定の仕方は「Console」というフォルダ内にある「WriteLine」ファイルを実行する、というのと似ています。
「Console」フォルダ内には「WriteLine」ファイル以外にもたくさんのファイルが含まれています。
「Console」フォルダ自体もさらに別の上位のフォルダに格納されています。

このファイルとフォルダのような階層的な構造をコード上で表現するのが名前空間です。

■名前空間のイメージ
名前空間のイメージ

この階層は「.」(ドット)記号で区切って表します。
Windowsのフォルダ構造では「\」(円記号)を使用するのと同じです。

usingディレクティブ

上記の画像の通り、コンソール画面に文字列を出力する「WriteLine」メソッドは、正しくは「System.Console.WriteLine」という場所に存在します。
しかしいままで説明してきたコード中では「Console.WriteLine」という形で実行できています。
これを可能にしているのがコード先頭のusingディレクティブです。

以下はVisual Studioでプロジェクトを作成した時に自動的に生成されるコードです。
(.Net Framework4.5)


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

//ここまでがusingディレクティブ

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }
}

usingディレクティブは名前空間の指定を省略して記述できるようにするものです。
「using System;」は「"System"内に存在するキーワードの記述は、"System"を省略して記述を可能にする」という効果があります。

例えば「using System;」をコードから削除してみると、「Console.WriteLine」の箇所でエラーとなります。


//using System; //←コメントアウトしてみる
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            //エラー
            Console.WriteLine("aaa");
        }
    }
}

Visual Studioの場合は「Console」の下に赤線が引かれて「Consoleが見つからない」というエラーが表示されます。

これは「Console」が使えなくなったのではなく、見つからない(どこにあるのかが分からない)というだけです。
以下のように場所を明確に記述すれば使用することができます。


//using System; //←コメントアウトしてみる
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            //「System」から記述する
            System.Console.WriteLine("aaa");
        }
    }
}

usingによる省略形を使用しない記述を完全修飾名といいます。

エイリアス

usingを使用すれば特定のクラスに対するショートカットを作ることができます。
例えばファイル操作にはFileクラスを使用しますが、Fileクラスは「System.IO.File」に存在します。
なので、普通は以下のどちらかで記述します。


using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            //完全修飾名でアクセス
            System.IO.File.ReadAllText("test.txt");
        }
    }
}

using System;
using System.IO; //←これを追加

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            //usingディレクティブにより省略形で書ける
            File.ReadAllText("test.txt");
        }
    }
}

毎回「System.IO.File.○○」と書くのはやや面倒ですから、省略して書ける後者のほうが便利です。
しかしこの記述をすると「System.IO」内にあるすべてのオブジェクトに対して省略形の記述が有効になります。
「System.IO.File」だけを省略形で記述したい場合は以下のようにします。


using System;

//「F」は「System.IO.File」の別名になる
using F = System.IO.File;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            F.ReadAllText("test.txt");
            //↑は↓と同じ意味
            System.IO.File.ReadAllText("test.txt");
        }
    }
}

このようにすると、コード中の「F」は「System.IO.File」の別名として扱われます。
これをエイリアスといいます。
エイリアス名は自由に付けることができます。

名前空間の定義

名前空間は自分で定義することもできます。
Visual Studioでコードを自動生成した時、プロジェクト名の名前空間が自動的に定義されています。


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

//↓これが名前空間の定義
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }
}

名前空間の定義はnamespaceというキーワードで行います。
そのまんま「名前」「空間」という直訳です。
namespaceブロック内が新しい名前空間として定義されます。

自動生成される名前空間以外にも自分で定義可能です。


using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            //名前空間「Test」の中の「Program.number」にアクセス
            int num = Test.Program.number;

            Console.WriteLine(num);
            Console.ReadLine();
        }
    }
}

//「Test」という名前空間の定義
namespace Test
{
    class Program
    {
        public static int number = 1;
    }
}
1

自分で定義した名前空間へのアクセスの仕方も今までと同じです。

上記コードでは「Program」というクラスが二つ存在しますが「ConsoleApplication1.Program」と「Test.Program」という別の名前空間に存在するので、別物と識別できます。

名前空間は入れ子にして定義することもできます。


namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            int num1 = Test.AAA.Program.number; //1
            int num2 = Test.BBB.Program.number; //2
        }
    }
}

namespace Test
{
    namespace AAA
    {
        class Program
        {
            public static int number = 1;
        }
    }

    namespace BBB
    {
        class Program
        {
            public static int number = 2;
        }
    }
}

名前空間は同じ名前を重複して付けることができます。
重複というよりも複数に分割できる、といった方が正しいかもしれません。
これはソースコードを複数に分ける時などに使用します。


namespace Test
{
    class Program
    {
    }
}

namespace Test
{
    class Program2
    {
    }

    //同じ名前はダメ
    class Program
    {
    }
}

コード上は分けられていても同じ名前空間内では同じ名前のオブジェクトは定義できません。
上記の例では上段の名前空間「Test」内に「Program」クラスがすでに定義されているので、下段の名前空間「Test」では「Program」クラスは定義できません。