.NETのすべての型は、名前空間と型名からなる完全な名前を持っています:System.Console、System.Collections.Generic.List<T>、System.Text.StringBuilder。名前空間は関連する型をまとめ、名前の衝突を防ぐので、自分の Order や Timer クラスをライブラリのものと共存させられます。ファイルの先頭のusingディレクティブは名前空間をインポートし、短い名前を使えるようにします。
出力:
Cart: tea, honey
1
usingディレクティブが影響するのは、コンパイル時の名前だけです。ライブラリを読み込んだり、プログラムにコードを追加したりはしません。どのライブラリが使えるかは、プロジェクトの参照とNuGetパッケージで決まります。コンパイラが、型や名前空間が「could not be found (are you missing a using directive or an assembly reference?)」(エラーCS0246)と報告したら、usingの行が抜けているか、パッケージが参照されていません。
独自の名前空間を宣言する
型を namespace ブロックの中に置きます。名前空間は入れ子にでき、ドットで書け、同じ名前空間を多くのファイルに分けることもできます。
出力:
120.00 via DHL
Shop.Billing.Invoice
namespace Shop.Billing { } は namespace Shop { namespace Billing { } } の省略形です。名前はまず外側の名前空間から探されるので、Shop の中のコードは Shop. の接頭辞なしで Billing.Invoice を参照できます。
慣例:会社名や製品名(Contoso.Payments)で始め、次に機能や層を続け、フォルダー構成に合わせます(Contoso.Payments/Refunds/RefundService.cs には Contoso.Payments.Refunds が入ります)。クラスに名前空間と同じ名前(Shop.Shop)を付けてはいけません。あちこちでぎこちない修飾が必要になります。
エイリアス
using Name = Namespace.Type; は、型(または名前空間)にローカルな名前を付けます。使う場面は2つで、長いジェネリック型を短くする場合と、衝突を解決する場合です。
出力:
latte: 3.60
order 17
エイリアスは、(後述の global でない限り)宣言したファイルにしか適用されません。C# 12以降では、タプルや配列を含む任意の型にエイリアスを付けられます:using Point = (int X, int Y);。
あいまいな参照(CS0104)
インポートした2つの名前空間に同じ名前の型があると、短い名前を使うとエラーになります。典型的な例は Timer で、System.Threading、System.Timers、(デスクトップアプリでは)System.Windows.Forms にあります。
using System.Threading;
using System.Timers;
var t = new Timer(1000);
// error CS0104: 'Timer' is an ambiguous reference between
// 'System.Timers.Timer' and 'System.Threading.Timer'
直し方は3つあり、最も局所的なものから順に、完全修飾名を書く(new System.Timers.Timer(1000))、どちらを意味するかを示すエイリアスを追加する、不要なディレクティブを削除する、です。
出力:
250
System.Timers.Timer
System.Threading.Timer
自分の名前空間が System や Console という型を定義している場合は、接頭辞 global:: でルートからの検索を強制できます:global::System.Console.WriteLine("hi");。自動生成されるコードは、この理由からどこでもそれを使っています。
using static
using static は1つの型の静的メンバーをインポートするので、型名なしで呼び出せます。Math のように同じクラスを何度も呼ぶコードに向いています。
出力:
Area: 28.27
Hypotenuse: 5
42
using static はenum(using static System.DayOfWeek; で Monday と書けます)や自分で作った静的クラスにも使えます。短い名前でもあいまいにならない場所で使います。大きなファイルで単に WriteLine と書くと、どのライターなのかと読み手を迷わせることがあります。
global usingとファイルスコープの名前空間(C# 10)
C# 10の2つの機能で、ファイルの先頭の定型文が減りました。global usingはプロジェクトのすべてのファイルに適用され、通常は GlobalUsings.cs のような1つのファイルにまとめます。
// GlobalUsings.cs, C# 10 and later
global using System;
global using System.Collections.Generic;
global using System.Linq;
global using Money = System.Decimal;
.NET 6以降のSDKプロジェクトでは、これらを生成させることもできます。.csproj に <ImplicitUsings>enable</ImplicitUsings> があると(新しいテンプレートでは既定)、コンソールプロジェクトには System、System.Collections.Generic、System.IO、System.Linq、System.Net.Http、System.Threading、System.Threading.Tasks が入り、WebプロジェクトにはさらにASP.NET Coreの名前空間が入ります。現代的な Program.cs ファイルがいきなりコードから始まるのはそのためです。
ファイルスコープの名前空間は、ブロックの代わりにセミコロンでファイル全体の名前空間を宣言し、インデントを1段減らします。
// C# 10 and later
namespace Shop.Billing;
public class Invoice
{
public decimal Amount { get; set; }
}
1つのファイルに書けるファイルスコープの名前空間は1つだけで、同じファイルでブロックの名前空間と混ぜることはできません。古いプロジェクト、Unityのスクリプト、.NET Frameworkを対象とするコードでは、前に示したブロックの形を使います。
usingディレクティブを置く場所とusingステートメント
usingディレクティブは、ファイル内のどの名前空間や型の宣言よりも前に置く必要があります(global usingは他のすべてより前)。名前空間のブロックの中に置くこともでき、その場合はそこにだけ適用されます。スタイルガイドによって異なりますが、ほとんどの.NETのコードは先頭に置いています。
キーワード using には、メソッドの中でもう1つ、無関係な役割があります。usingステートメント using (var file = File.OpenRead(path)) { ... } は、ブロックの終わりでオブジェクトの Dispose を呼び、ファイルや接続を閉じます。共通しているのはキーワードだけです。usingステートメントのページを参照してください。
よくある質問
C#のusingは何をしますか?
ファイルの先頭の using System.Text; は名前空間をインポートするディレクティブで、System.Text.StringBuilder の代わりに StringBuilder と書けるようにします。コードを追加したり何かを読み込んだりはせず、名前を短くするだけです。メソッドの中の using (var f = ...) は、ブロックの終わりでオブジェクトを破棄するusingステートメントという別の機能です。
C#の名前空間とは何ですか?
名前空間は、名前の衝突を防ぎ、コードを整理するための、名前の付いた型のグループです。System.Collections.Generic や MyShop.Billing などがあります。異なる名前空間にあれば、2つのクラスは同じ名前を持てます。慣例として、名前空間はフォルダー構成に合わせ、会社名や製品名で始めます。
C#のusing staticとは何ですか?
using static System.Math; は1つの型の静的メンバーをインポートするので、Math. の接頭辞なしで Sqrt(16) を呼び、PI を読めます。自分で作ったクラスやenumを含め、どのクラスにも使えます。数学的な処理の多いコードなど、短い名前でも意味が明確な場所で使います。
C#の「is an ambiguous reference」はどう直しますか?
エラーCS0104は、インポートした2つの名前空間の両方にその名前の型があることを意味します。たとえば System.Threading と System.Timers の Timer です。完全修飾名(System.Timers.Timer)を書くか、usingディレクティブの一方を削除するか、エイリアスを追加します:using Timer = System.Timers.Timer;。
C#のglobal usingとは何ですか?
global using System.Text;(C# 10)は、それが書かれたファイルだけでなく、プロジェクトのすべてのファイルに名前空間をインポートします。.NET 6以降のSDKプロジェクトでは、<ImplicitUsings>enable</ImplicitUsings> が設定されているとglobal usingが自動で生成されます。新しい Program.cs ファイルにusingの行がないのはそのためです。