C#の名前空間とusingを都道府県で理解しよう

広告

C#のコードでよく見かけるnamespaceusing。どちらも名前に関係する機能ですが、役割の違いが分かりにくいと感じることがあります。

この記事では、名前空間を都道府県に例えて説明します。ポイントは「同じ名前を所属先によって区別する」という考え方です。

この例えは、地理とプログラムが完全に同じ構造だという意味ではありません。名前を分類し、区別する仕組みを理解するためのモデルです。

名前空間は「都道府県」のようなもの

日本には、同じ名前の市が複数あります。たとえば「府中市」は東京都と広島県の両方に存在します。「府中市」だけではどちらか判断できませんが、都道府県名を付ければ区別できます。

東京都府中市と広島県府中市を所属先で区別する図解
同じ「府中市」でも、東京都と広島県では異なる名前として区別できます
namespace Tokyo
{
    public class Fuchu
    {
    }
}

namespace Hiroshima
{
    public class Fuchu
    {
    }
}

どちらにもFuchuクラスがありますが、所属する名前空間が異なるため、別の型として扱われます。名前空間を含めた正式な名前を完全修飾名といいます。

Tokyo.Fuchu tokyoFuchu = new Tokyo.Fuchu();
Hiroshima.Fuchu hiroshimaFuchu = new Hiroshima.Fuchu();

名前空間を使う2つの理由

  1. 同じ名前の衝突を避ける
    別のライブラリに同名のクラスがあっても、名前空間で区別できます。
  2. 関連する型を整理する
    キャラクター、アイテム、画面など、役割ごとに型をまとめられます。
namespace MyGame.Characters
{
    public class Player { }
    public class Enemy { }
}

namespace MyGame.Items
{
    public class Sword { }
    public class Potion { }
}

MyGame.Characters.Playerのように、ピリオドで区切って階層的に表せます。ただし、名前空間は住所やフォルダーそのものではありません。フォルダー構成とそろえると管理しやすくなりますが、C#の仕組み上は別のものです。

usingは名前を短く書くための指定

完全修飾名を毎回書けば確実ですが、コードが長くなります。そこで使うのがusingディレクティブです。

usingによって長い名前を短く記述するイメージ
usingは、型を探すときの「よく使う所属先」を指定します
using Tokyo;

Fuchu city = new Fuchu();

using Tokyo;を書くと、コンパイラーはFuchuという単純な名前を解決するときに、Tokyo名前空間に所属する型も候補として探します。

「これから府中市と言った場合は、東京都の中からも探してください」と伝えるイメージです。

usingを書いても、クラスが移動したりコピーされたりするわけではありません。また、ライブラリをインストールする命令でもありません。Tokyo.FuchuFuchuと短く記述できるようになるだけです。

同じ名前が2つ見つかったら?

東京都と広島県の両方をusingし、どちらにもFuchuがある場合を考えます。

using Tokyo;
using Hiroshima;

Fuchu city = new Fuchu(); // どちらのFuchu?
同名クラスの曖昧さを完全修飾名で解決するイメージ
候補が複数あるときは、所属先まで指定して曖昧さを解消します

この場合は完全修飾名を使うか、usingで別名を付けます。

Tokyo.Fuchu city = new Tokyo.Fuchu();
using TokyoFuchu = Tokyo.Fuchu;
using HiroshimaFuchu = Hiroshima.Fuchu;

TokyoFuchu city1 = new TokyoFuchu();
HiroshimaFuchu city2 = new HiroshimaFuchu();

SystemとUnityEngineで確認しよう

普段使っているSystemUnityEngineも名前空間です。たとえばConsoleの完全修飾名はSystem.Consoleです。

using System;
using UnityEngine;

Console.WriteLine("こんにちは");
GameObject player = new GameObject("Player");

using System;がなければSystem.Consoleusing UnityEngine;がなければUnityEngine.GameObjectと書けます。つまり、usingがなくても完全修飾名を使えば型を指定できます。

名前空間とスコープは同じではない

名前空間にも名前を参照できる範囲という側面はありますが、ローカル変数のスコープやpublicprivateによるアクセス制御とは目的が異なります。

  • 名前空間:型を分類し、同名の型を区別する
  • 変数のスコープ:変数名を参照できるコード上の範囲を決める
  • アクセス修飾子:別の型などからメンバーへアクセスできるかを決める

まとめ

  • 名前空間は、都道府県のように「所属先を含む名前」を作る
  • 同名のクラスでも、名前空間が違えば区別できる
  • usingは、型名を短く書くための名前解決の指定
  • usingは、機能のインストールやクラスのコピーではない
  • 名前が曖昧なときは、完全修飾名または別名を使う

まずは「名前空間=都道府県」「クラス=市や施設」「using=よく使う都道府県名を省略するための指定」と捉えると、コードを読みやすくなります。

訪問数 6 回, 今日の訪問数 6回

広告