`using` 지시문: 네임스페이스에서 타입 가져오기
using 지시문: 네임스페이스에서 타입 가져오기
using 지시문은 타입의 정규화된 네임스페이스(fully qualified namespace)를 일일이 지정하지 않아도 그 네임스페이스에 정의된 타입을 쓸 수 있게 해 줘요. 가장 기본적인 형태로는 하나의 네임스페이스에 있는 모든 타입을 가져오는데, 다음처럼 적어요.
using System.Text;
이 using 지시문에는 두 가지 한정자(modifier)를 붙일 수 있어요.
global한정자는 같은 지시문을 프로젝트의 모든 소스 파일에 추가한 것과 같은 효과를 줘요.static한정자는 네임스페이스의 모든 타입을 가져오는 대신, 단일 타입의static멤버와 중첩 타입만 가져와요.
두 한정자를 함께 쓰면 어떤 타입의 static 멤버를 프로젝트의 모든 소스 파일에서 쓸 수 있게 만들 수 있어요.
네임스페이스나 타입에 별칭(alias)을 붙이는 using alias 지시문도 만들 수 있어요.
using Project = PC.MyCompany.Project;
이 using alias 지시문에도 global 한정자를 쓸 수 있어요.
[!NOTE]
using키워드는 파일이나 폰트 같은 xref:System.IDisposable 객체를 올바르게 처리해 주는 *using문(statement)*을 만들 때도 쓰여요.using문에 대한 자세한 내용은usingstatement 문서를 참고해요.
global 한정자가 없는 using 지시문의 범위(scope)는 그 지시문이 나타난 파일 하나로 한정돼요.
global using 지시문은 모든 네임스페이스 및 타입 선언보다 앞에 와야 해요. 그리고 모든 global using 지시문은 소스 파일에서 global이 아닌 using 지시문보다 앞에 와야 해요.
그 외의 using 지시문은 다음과 같은 위치에 둘 수 있어요.
- 소스 코드 파일의 맨 앞. 네임스페이스나 타입 선언보다 앞쪽.
- 블록 범위 네임스페이스(block-scoped namespace) 안쪽. 단, 그 네임스페이스에 선언된 다른 네임스페이스나 타입보다 앞.
이 외의 위치에 두면 컴파일 오류가 나요.
using 지시문을 만들면 네임스페이스를 매번 지정하지 않고도 그 네임스페이스의 타입을 쓸 수 있어요. 단, using 지시문은 지정한 네임스페이스 안에 중첩되어 있는 네임스페이스까지 접근할 수 있게 해 주지는 않아요. 네임스페이스는 사용자 정의(user-defined)와 시스템 정의(system-defined) 두 종류가 있는데, 사용자 정의 네임스페이스는 여러분이 코드에 정의한 네임스페이스를 말하고, 시스템 정의 네임스페이스의 목록은 .NET API Browser에서 확인할 수 있어요.
본문
global 한정자
using 지시문에 global 한정자를 붙이면 그 using을 컴파일의 모든 파일(보통은 프로젝트 전체)에 적용해요.
global using <fully-qualified-namespace>;
여기서 fully-qualified-namespace는 네임스페이스를 지정하지 않고도 참조할 수 있는 타입들이 들어 있는 네임스페이스의 정규화된 이름이에요.
global using 지시문은 어떤 소스 파일의 맨 앞이든 둘 수 있어요. 한 파일 안의 모든 global using 지시문은 다음보다 앞에 와야 해요.
global한정자가 붙지 않은 모든using지시문.- 파일 안의 모든 네임스페이스 및 타입 선언.
global using 지시문은 아무 소스 파일에나 추가할 수 있어요. 보통은 한곳에 모아 두는 편이에요. global using 지시문의 순서는 한 파일 안에서든 파일 사이에서든 상관없어요.
global 한정자는 static 한정자와 함께 쓸 수도 있고, using alias 지시문에도 적용할 수 있어요. 두 경우 모두 지시문의 범위는 현재 컴파일의 모든 파일이에요. 다음 예시는 프로젝트의 모든 파일에서 xref:System.Math?displayProperty=fullName에 선언된 모든 메서드를 쓸 수 있게 해 줘요.
global using static System.Math;
프로젝트 파일에 <Using> 항목을 추가해 네임스페이스를 전역으로 포함시킬 수도 있어요. 예를 들면 <Using Include="My.Awesome.Namespace" />처럼요. 자세한 내용은 <Using> item 문서를 참고해요.
분석기(Analyzer)는 서로 다른 위치에 global using 지시문이 중복되면 진단 메시지를 내 보내요. 이 분석기는 이미 global using 지시문이 참조하고 있는 네임스페이스나 타입을 위한 using 지시문을 추가했을 때도 알려 줘요. global using을 관리하기 쉽게 하려면 프로젝트에서 한 파일에 모아 두는 게 좋아요.
static 한정자
using static 지시문은 타입 이름을 지정하지 않고도 접근할 수 있는 static 멤버와 중첩 타입을 가진 타입을 지정해요. 문법은 이렇게 돼요.
// not within a namespace
using static <fully-qualified-type-name>;
여기서 <fully-qualified-type-name>은 타입 이름을 지정하지 않고도 참조할 수 있는 static 멤버와 중첩 타입을 가진 타입의 이름이에요. 정규화된 타입 이름(네임스페이스 이름과 타입 이름 전체)을 제공하지 않으면 C#은 CS0246 컴파일 오류를 내요. 오류 내용은 "The type or namespace name 'type/namespace' couldn't be found (are you missing a using directive or an assembly reference?)"예요.
using static 지시문을 네임스페이스의 문맥 안(파일 범위든 namespace 블록에 중첩된 위치든)에서 적용하면 타입을 완전히 정규화할 필요가 없어요.
using static 지시문은 static 멤버(또는 중첩 타입)를 가진 타입이라면 인스턴스 멤버도 함께 가진 타입에도 적용돼요. 다만 인스턴스 멤버는 타입 인스턴스를 통해서만 호출할 수 있어요.
타입 이름으로 접근을 한정하지 않고도 타입의 static 멤버에 접근할 수 있어요.
using static System.Console;
using static System.Math;
class Program
{
static void Main()
{
WriteLine(Sqrt(3*3 + 4*4));
}
}
보통 static 멤버를 호출할 때는 멤버 이름과 함께 타입 이름을 적어요. 같은 타입 이름을 반복해서 적다 보면 코드가 장황해지고 읽기 어려워질 수 있어요. 예를 들어 다음 Circle 클래스 정의는 xref:System.Math 클래스의 멤버를 아주 많이 참조해요.
:::code language="csharp" source="./snippets/using-static1.cs" id="Snippet1":::
using static 지시문으로 멤버를 참조할 때마다 xref:System.Math 클래스를 명시적으로 참조할 필요를 없애면 코드가 더 깔끔해져요.
:::code language="csharp" source="./snippets/using-static2.cs":::
using static은 지정한 타입에 선언된 접근 가능한 static 멤버와 중첩 타입만 가져와요. 상속된 멤버는 가져오지 않아요. Visual Basic 모듈을 포함해 using static 지시문으로 아무 이름 있는 타입에서든 가져올 수 있어요. F# 최상위 함수가 메타데이터에 유효한 C# 식별자 이름을 가진 이름 있는 타입의 static 멤버로 나타나면 그 F# 함수도 가져올 수 있어요.
using static은 지정한 타입에 선언된 확장 멤버(extension member)를 확장 멤버 조회에 사용할 수 있게 만들어요. 다만 확장 멤버의 이름 자체가 코드에서 한정 없이 참조할 수 있도록 범위로 가져와지지는 않아요.
같은 컴파일 단위나 네임스페이스에서 서로 다른 using static 지시문이 가져온 같은 이름의 메서드들은 메서드 그룹(method group)을 이뤄요. 이 메서드 그룹 안의 오버로드 해석은 일반적인 C# 규칙을 따라요.
다음 예시는 xref:System.Console, xref:System.Math, xref:System.String 클래스의 static 멤버를 타입 이름을 지정하지 않고 쓸 수 있게 using static 지시문을 사용하는 모습을 보여 줘요.
:::code language="csharp" source="./snippets/using-static3.cs" id="Snippet1":::
이 예시에서 xref:System.Double 타입에도 using static 지시문을 적용할 수 있어요. 그 지시문을 추가하면 타입 이름을 지정하지 않고도 xref:System.Double.TryParse(System.String,System.Double@) 메서드를 호출할 수 있게 돼요. 다만 타입 이름 없이 TryParse를 쓰면 어떤 숫자 타입의 TryParse 메서드가 호출되는지 확인하려면 using static 지시문을 살펴봐야 하므로 코드를 오히려 덜 읽기 쉽게 만들어요.
using static은 enum 타입에도 적용돼요. enum과 함께 using static을 추가하면 멤버에 접근할 때 enum 타입을 쓸 필요가 없어져요.
using static Color;
enum Color
{
Red,
Green,
Blue
}
class Program
{
public static void Main()
{
Color color = Green;
}
}
using 별칭
식별자를 네임스페이스나 타입으로 더 쉽게 한정하기 위해 using alias 지시문을 만들어요. 어떤 using 지시문에서든 그 앞에 온 using 지시문과 무관하게 정규화된 네임스페이스나 타입을 써야 해요. using 지시문의 선언에는 using 별칭을 쓸 수 없어요. 예를 들어 다음 예시는 컴파일 오류를 내요.
using s = System.Text;
using s.RegularExpressions; // Generates a compiler error.
다음 예시는 네임스페이스에 대한 using 별칭을 정의하고 사용하는 모습을 보여 줘요.
:::code language="csharp" source="./snippets/csrefKeywordsNamespace2.cs" id="Snippet8":::
using alias 지시문의 오른쪽에는 개방형 제네릭 타입(open generic type)이 올 수 없어요. 예를 들어 List<T>에 대해선 using 별칭을 만들 수 없지만 List<int>에 대해서는 만들 수 있어요.
다음 예시는 클래스에 대한 using 지시문과 using 별칭을 정의하는 모습을 보여 줘요.
:::code language="csharp" source="./snippets/csrefKeywordsNamespace2.cs" id="Snippet9":::
C# 12부터는 이전에는 제한됐던 타입들, 예컨대 튜플 타입, 포인터 타입, 그 외의 unsafe 타입에도 별칭을 만들 수 있어요. 갱신된 규칙에 대한 자세한 내용은 C# 표준의 §14.6.2 Using alias directives를 참고해요.
정규화된 별칭 멤버
:: 네임스페이스 별칭 한정자는 다른 엔터티가 가려 버릴 수도 있는 전역 네임스페이스나 다른 using 별칭에 명시적으로 접근할 수 있게 해 줘요.
global::은 :: 토큰 다음에 오는 네임스페이스 조회가 전역 네임스페이스를 기준으로 이뤄지게 보장해 줘요. 그 외에는 토큰이 using 별칭으로 해석되어야 하고, :: 다음에 오는 토큰은 그 별칭이 붙은 네임스페이스 안의 타입으로 해석되어야 해요. 다음 예시는 두 형태를 모두 보여 줘요.
:::code language="csharp" source="./snippets/UsingAliasQualifier.cs" id="UsingAliasQualifier":::
C# 언어 사양
더 자세한 내용은 C# Language Specification의 Using directives를 참고해요. 언어 사양은 C# 구문과 사용법의 최종 권위(정의)가 되는 문서예요.
global using 한정자에 대한 자세한 내용은 Global using directives를 참고해요.
더 알아보기
- C# keywords
- Namespaces
- Style rule IDE0005 - Remove unnecessary 'using' directives
- Style rule IDE0065 - 'using' directive placement
usingstatement