Quick Reference
namespace는 타입의 정식 이름을 나누는 논리적 경계이고, using directive는 그 파일이나 프로젝트에서 긴 이름을 생략하게 합니다. using directive는 자원을 해제하지 않습니다. 자원 수명은 using statement/declaration으로 관리합니다.
using System.Text;
using JsonSerializer = System.Text.Json.JsonSerializer;
using static System.Math;
namespace RefDock.Services;
public sealed class SlugService
{
public string Serialize(object value) => JsonSerializer.Serialize(value);
public double Root(double value) => Sqrt(value);
}- 파일 전체가 하나의 namespace면 C# 10+
namespace RefDock.Services;를 씁니다. - 같은 이름의 타입이 충돌하면 alias 또는
global::로 정식 이름을 씁니다. - 프로젝트 전체 공통 import만
global using으로 올립니다.
namespace 선언
블록 namespace와 file-scoped namespace는 타입을 같은 정식 이름 아래에 선언하는 두 문법입니다. 한 파일에 타입 하나의 namespace만 둘 때는 file-scoped 문법이 들여쓰기를 줄입니다. file-scoped namespace는 파일 안에 하나만 선언할 수 있고, 같은 파일에서 block namespace와 섞지 않습니다.
namespace RefDock.Domain
{
public sealed record Card(string Slug); // block namespace
}
// 별도 파일
namespace RefDock.Domain;
public sealed record Category(string Name); // file-scoped namespacenamespace는 폴더 구조나 assembly 경계를 강제하지 않습니다. RefDock.Domain.Card라는 정식 이름을 구성할 뿐입니다. 공개 API의 namespace는 소비자가 import하는 표면이므로, 폴더 정리만을 이유로 자주 바꾸면 source compatibility를 해칠 수 있습니다.
using directive의 범위
일반 using의 범위는 선언한 소스 파일입니다. 가져온 namespace의 바로 아래 타입만 짧게 쓸 수 있으며, 중첩 namespace까지 자동으로 가져오지는 않습니다.
using System.Collections.Generic;
using System.Text.Json;
List<string> tags = [];
JsonSerializerOptions options = new();directive는 파일의 namespace·type 선언보다 앞에 두거나, block namespace 안에서 그 namespace의 타입 선언보다 앞에 둡니다. namespace를 import하는 것뿐이므로 런타임 객체 생성, assembly 자동 로드, Dispose 호출을 일으키지 않습니다.
using static은 지정 타입의 static member와 nested type을 type name 없이 쓰게 합니다. 일반적인 도메인 타입에 남용하면 호출 원본을 찾기 어려워지므로, Math처럼 출처가 분명한 경우에 제한합니다.
alias와 global using
alias는 타입 또는 namespace에 짧은 지역 이름을 붙입니다. 동일한 단순 이름이 충돌할 때는 alias가 가장 직접적입니다.
using TextJson = System.Text.Json.JsonSerializer;
using JsonDocument = System.Text.Json.JsonDocument;
string json = TextJson.Serialize(new { Name = "Mina" });
using JsonDocument document = JsonDocument.Parse(json);두 라이브러리에 같은 타입명이 있으면 global::System.Text.Json.JsonSerializer처럼 루트부터 쓰는 방법도 있습니다. alias 이름은 해당 파일에서만 유효하므로, 외부 API 시그니처에 alias 자체가 노출되지는 않습니다.
global using은 현재 compilation의 모든 파일에 import를 적용합니다. 모든 global using은 같은 파일의 일반 using, namespace, type 선언보다 앞에 와야 합니다. SDK의 implicit usings도 이 기능을 이용하므로 프로젝트 설정을 확인한 뒤 중복 선언을 줄입니다.
// GlobalUsings.cs
global using System;
global using System.Collections.Generic;자주 틀리는 부분
using System;은System.IO나System.Text까지 import하지 않습니다.usingdirective와using var은 이름만 같고 역할이 다릅니다.- global using에 프로젝트 내부 namespace를 과도하게 넣으면 타입의 출처와 의존성이 흐려집니다.
- 타입 충돌을 해결하려고 무작정 using을 지우기보다 alias 또는 정식 이름으로 의도를 남깁니다.
참고 링크
2 sources