22개 특성
22.1 일반
대부분의 C# 언어를 사용하면 프로그래머가 프로그램에 정의된 엔터티에 대한 선언적 정보를 지정할 수 있습니다. 예를 들어 클래스에서 메서드의 접근성은 method_modifier public
private
데코레이팅하여 지정됩니다.
C#을 사용하면 프로그래머가 특성이라는 새로운 종류의 선언적 정보를 발명할 수 있습니다. 프로그래머는 다양한 프로그램 엔터티에 특성을 연결하고 런타임 환경에서 특성 정보를 검색할 수 있습니다.
참고: 예를 들어 프레임워크는 특정 프로그램 요소(예: 클래스 및 메서드)에 배치하여 해당 프로그램 요소에서 설명서로의 매핑을 제공할 수 있는 특성을 정의
HelpAttribute
할 수 있습니다. 끝 메모
특성은 위치 및 명명된 매개 변수(§22.2.3)를 가질 수 있는 특성 클래스(§22.2)의 선언을 통해 정의됩니다. 특성은 특성 사양(§22.3)을 사용하여 C# 프로그램의 엔터티에 연결되며 런타임에 특성 인스턴스(§22.4)로 검색할 수 있습니다.
22.2 특성 클래스
22.2.1 일반
직간접적으로 추상 클래스에서 파생되는 클래스System.Attribute
는 특성 클래스입니다. 특성 클래스의 선언은 프로그램 엔터티에 배치할 수 있는 새로운 종류의 특성을 정의합니다. 규칙에 따라 특성 클래스의 이름은 접미사 Attribute
로 지정됩니다. 특성의 사용은 이 접미사를 포함하거나 생략할 수 있습니다.
제네릭 클래스 선언은 직접 또는 간접 기본 클래스로 사용할 System.Attribute
수 없습니다.
예제:
public class B : Attribute {} public class C<T> : B {} // Error – generic cannot be an attribute
끝 예제
22.2.2 특성 사용량
특성 AttributeUsage
(§22.5.2)은 특성 클래스를 사용하는 방법을 설명하는 데 사용됩니다.
AttributeUsage
에는 특성 클래스가 사용할 수 있는 프로그램 엔터티의 종류를 지정할 수 있는 위치 매개 변수(§22.2.3)가 있습니다.
예제: 다음 예제에서는 class_declaration 및 interface_declaration
SimpleAttribute
경우에만 배치할 수 있는 명명된 특성 클래스를 정의하고 특성의 여러 용도를Simple
보여 줍니다.[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)] public class SimpleAttribute : Attribute { ... } [Simple] class Class1 {...} [Simple] interface Interface1 {...}
이 특성은 이름으로
SimpleAttribute
정의되어 있지만 이 특성을 사용하면Attribute
접미사를 생략하여 짧은 이름을Simple
생성할 수 있습니다. 따라서 위의 예제는 의미상 다음과 같습니다.[SimpleAttribute] class Class1 {...} [SimpleAttribute] interface Interface1 {...}
끝 예제
AttributeUsage
지정된 엔터티에 대해 특성을 두 번 이상 지정할 수 있는지 여부를 나타내는 명명된 매개 변수(§22.2.3)가 있습니다 AllowMultiple
. 특성 클래스의 경우 AllowMultiple
해당 특성 클래스는 다중 사용 특성 클래스이며 엔터티에서 두 번 이상 지정할 수 있습니다. 특성 클래스가 false이거나 지정되지 않은 경우 AllowMultiple
해당 특성 클래스는 단일 사용 특성 클래스이며 엔터티에서 최대 한 번 지정할 수 있습니다.
예제: 다음 예제에서는 명명
AuthorAttribute
된 다중 사용 특성 클래스를 정의하고 두 가지 특성을 사용하는 클래스 선언을Author
보여 줍니다.[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] public class AuthorAttribute : Attribute { public string Name { get; } public AuthorAttribute(string name) => Name = name; } [Author("Brian Kernighan"), Author("Dennis Ritchie")] class Class1 { ... }
끝 예제
AttributeUsage
에는 기본 클래스에 지정된 특성이 해당 기본 클래스에서 파생된 클래스에 의해 상속되는지 여부를 나타내는 또 다른 명명된 매개 변수(§22.2.3)가 있습니다 Inherited
. 특성 클래스가 true이면 Inherited
해당 특성이 상속됩니다. 특성 클래스가 false이면 Inherited
해당 특성이 상속되지 않습니다. 지정되지 않은 경우 기본값은 true입니다.
특성 클래스 X
에 연결된 특성이 없는 AttributeUsage
경우(예:
class X : Attribute { ... }
는 다음과 같습니다.
[AttributeUsage(
AttributeTargets.All,
AllowMultiple = false,
Inherited = true)
]
class X : Attribute { ... }
22.2.3 위치 및 명명된 매개 변수
특성 클래스에는 위치 매개 변수와 명명된 매개 변수가 있을 수 있습니다. 특성 클래스에 대한 각 공용 인스턴스 생성자는 해당 특성 클래스에 대한 유효한 위치 매개 변수 시퀀스를 정의합니다. 특성 클래스에 대한 각 비정적 공용 읽기-쓰기 필드 및 속성은 특성 클래스에 대한 명명된 매개 변수를 정의합니다. 명명된 매개 변수를 정의하는 속성의 경우 해당 속성에는 public get 접근자와 public set 접근자가 모두 있어야 합니다.
예제: 다음 예제에서는 위치 매개 변수 하나와 명명된 매개
HelpAttribute
변수url
하나가 있는 명명Topic
된 특성 클래스를 정의합니다. 비정적 및 public이지만 속성Url
은 읽기/쓰기가 아니므로 명명된 매개 변수를 정의하지 않습니다. 이 특성의 두 가지 용도도 표시됩니다.[AttributeUsage(AttributeTargets.Class)] public class HelpAttribute : Attribute { public HelpAttribute(string url) // url is a positional parameter { ... } // Topic is a named parameter public string Topic { get; set; } public string Url { get; } } [Help("http://www.mycompany.com/xxx/Class1.htm")] class Class1 { } [Help("http://www.mycompany.com/xxx/Misc.htm", Topic ="Class2")] class Class2 { }
끝 예제
22.2.4 특성 매개 변수 형식
특성 클래스의 위치 및 명명된 매개 변수 형식은 다음과 같은 특성 매개 변수 형식으로 제한됩니다.
- 다음 형식 중 하나:
bool
, ,byte
,char
double
,float
,int
long
,sbyte
short
string
uint
ulong
ushort
, . -
object
형식입니다. -
System.Type
형식입니다. - 열거형 형식.
- 위 형식의 1차원 배열입니다.
- 이러한 형식 중 하나가 없는 생성자 인수 또는 공용 필드는 특성 사양에서 위치 또는 명명된 매개 변수로 사용할 수 없습니다.
22.3 특성 사양
특성 사양 은 이전에 정의된 특성을 프로그램 엔터티에 적용하는 것입니다. 특성은 프로그램 엔터티에 대해 지정된 추가 선언적 정보의 한 조각입니다. 전역 범위(포함하는 어셈블리 또는 모듈에 특성을 지정하기 위해) 및 type_declaration(§14.7), class_member_declarations(§15.3), interface_member_declarations(§)에서 특성을 지정할 수 있습니다. 18.4), struct_member_declarations (§16.3), enum_member_declarations (§19.2), accessor_declarations (§15.7.3), event_accessor_ declarations(§15.8), parameter_list요소(§15.6.2) 및 type_parameter_list요소(§15.2.3).
특성은 특성 섹션에 지정됩니다. 특성 섹션은 하나 이상의 특성에 대한 쉼표로 구분된 목록을 둘러싸는 대괄호 쌍으로 구성됩니다. 이러한 목록에 특성을 지정하는 순서와 동일한 프로그램 엔터티에 연결된 섹션이 정렬되는 순서는 중요하지 않습니다. 예를 들어 특성 사양 , [A][B]
[B][A]
[A, B]
및 [B, A]
동일합니다.
global_attributes
: global_attribute_section+
;
global_attribute_section
: '[' global_attribute_target_specifier attribute_list ']'
| '[' global_attribute_target_specifier attribute_list ',' ']'
;
global_attribute_target_specifier
: global_attribute_target ':'
;
global_attribute_target
: identifier
;
attributes
: attribute_section+
;
attribute_section
: '[' attribute_target_specifier? attribute_list ']'
| '[' attribute_target_specifier? attribute_list ',' ']'
;
attribute_target_specifier
: attribute_target ':'
;
attribute_target
: identifier
| keyword
;
attribute_list
: attribute (',' attribute)*
;
attribute
: attribute_name attribute_arguments?
;
attribute_name
: type_name
;
attribute_arguments
: '(' ')'
| '(' positional_argument_list (',' named_argument_list)? ')'
| '(' named_argument_list ')'
;
positional_argument_list
: positional_argument (',' positional_argument)*
;
positional_argument
: argument_name? attribute_argument_expression
;
named_argument_list
: named_argument (',' named_argument)*
;
named_argument
: identifier '=' attribute_argument_expression
;
attribute_argument_expression
: non_assignment_expression
;
프로덕션 global_attribute_target 및 아래 텍스트의 경우 식별자에는 §6.4.3에 정의된 같음 또는 같 assembly
module
음의 맞춤법이 있어야 합니다. 프로덕션 module
법을 사용해야 합니다.
특성은 attribute_name 위치 및 명명된 인수의 선택적 목록으로 구성됩니다. 위치 인수(있는 경우)가 명명된 인수 앞에 옵니다. 위치 인수는 attribute_argument_expression 구성됩니다. 명명된 인수는 이름, 등호, attribute_argument_expression 함께 단순 할당과 동일한 규칙으로 제한됩니다. 명명된 인수의 순서는 중요하지 않습니다.
참고: 편의를 위해 array_initializer 허용되는 것처럼 후행 쉼표는 global_attribute_section attribute_section 허용됩니다(§17.7). 끝 메모
attribute_name 특성 클래스를 식별합니다.
특성이 전역 수준에 배치되면 global_attribute_target_specifier 필요합니다. global_attribute_target 같은 경우:
-
assembly
— 대상은 포함하는 어셈블리입니다. -
module
— 대상은 포함하는 모듈입니다.
global_attribute_target 다른 값은 허용되지 않습니다.
표준화된 attribute_target 이름은 event
, field
,method
, param
property
, return
type
및 typevar
. 이러한 대상 이름은 다음 컨텍스트에서만 사용해야 합니다.
-
event
— 이벤트입니다. -
field
— 필드입니다. 필드와 유사한 이벤트(즉, 접근자가 없는 이벤트)(§15.8.2) 및 자동으로 구현된 속성(§15.7.4)에도 이 대상의 특성이 있을 수 있습니다. -
method
— 생성자, 종료자, 메서드, 연산자, 속성 가져오기 및 설정 접근자, 인덱서 가져오기 및 설정 접근자, 이벤트 추가 및 제거 접근자입니다. 필드와 유사한 이벤트(즉, 접근자가 없는 이벤트)에도 이 대상의 특성이 있을 수 있습니다. -
param
- 속성 집합 접근자, 인덱서 집합 접근자, 이벤트 추가 및 제거 접근자 및 생성자, 메서드 및 연산자의 매개 변수입니다. -
property
- 속성 및 인덱서입니다. -
return
- 대리자, 메서드, 연산자, 속성 가져오기 접근자 및 인덱서 get 접근자입니다. -
type
- 대리자, 클래스, 구조체, 열거형 및 인터페이스입니다. -
typevar
— 형식 매개 변수입니다.
특정 컨텍스트는 둘 이상의 대상에 대한 특성의 사양을 허용합니다. 프로그램은 attribute_target_specifier 포함하여 대상을 명시적으로 지정할 수 있습니다. attribute_target_specifier 없으면 기본값이 적용되지만 attribute_target_specifier 사용하여 기본값을 확인하거나 재정의할 수 있습니다. 컨텍스트는 다음과 같이 해결됩니다.
- 대리자 선언의 특성에 대해 기본 대상은 대리자입니다. 그렇지 않으면 attribute_target 같은 경우:
-
type
— 대상이 대리자입니다. -
return
— 대상이 반환 값입니다.
-
- 메서드 선언의 특성에 대한 기본 대상은 메서드입니다. 그렇지 않으면 attribute_target 같은 경우:
-
method
— 대상이 메서드입니다. -
return
— 대상이 반환 값입니다.
-
- 연산자 선언의 특성에 대해 기본 대상은 연산자입니다. 그렇지 않으면 attribute_target 같은 경우:
-
method
— 대상이 연산자입니다. -
return
— 대상이 반환 값입니다.
-
- 속성 또는 인덱서 선언에 대한 get 접근자 선언의 특성에 대해 기본 대상은 연결된 메서드입니다. 그렇지 않으면 attribute_target 같은 경우:
-
method
— 대상은 연결된 메서드입니다. -
return
— 대상이 반환 값입니다.
-
- 속성 또는 인덱서 선언의 set 접근자에 지정된 특성의 경우 기본 대상은 연결된 메서드입니다. 그렇지 않으면 attribute_target 같은 경우:
-
method
— 대상은 연결된 메서드입니다. -
param
— 대상이 고독한 암시적 매개 변수입니다.
-
- 자동으로 구현된 속성 선언의 특성에 대해 기본 대상은 속성입니다. 그렇지 않으면 attribute_target 같은 경우:
-
field
— 대상은 속성에 대한 컴파일러 생성 지원 필드입니다.
-
- event_accessor_declarations 생략 하는 이벤트 선언에 지정된 특성의 경우 기본 대상은 이벤트 선언입니다. 그렇지 않으면 attribute_target 같은 경우:
-
event
— 대상은 이벤트 선언입니다. -
field
— 대상이 필드입니다. -
method
— 대상은 메서드입니다.
-
- event_accessor_declarations 생략 하지 않는 이벤트 선언의 경우 기본 대상이 메서드입니다.
-
method
— 대상은 연결된 메서드입니다. -
param
— 대상이 고독한 매개 변수입니다.
-
다른 모든 컨텍스트에서는 attribute_target_specifier 포함이 허용되지만 불필요합니다.
예: 클래스 선언은 지정자를
type
포함하거나 생략할 수 있습니다.[type: Author("Brian Kernighan")] class Class1 {} [Author("Dennis Ritchie")] class Class2 {}
끝 예제입니다.
구현은 구현이 정의된 다른 attribute_target수락할 수 있습니다. 이러한 attribute_target 인식하지 못하는 구현은 경고를 실행하고 포함된 attribute_section 무시해야 합니다.
규칙에 따라 특성 클래스의 이름은 접미사 Attribute
로 지정됩니다.
attribute_name 이 접미사를 포함하거나 생략할 수 있습니다. 특히 attribute_name 다음과 같이 해결됩니다.
- attribute_name 가장 오른쪽 식별자가 축자 식별자(§6.4.3)이면 attribute_name type_name(§7.8)로 확인됩니다. 결과가 파생된
System.Attribute
형식이 아니면 컴파일 시간 오류가 발생합니다. - 그렇지 않은 경우 입니다.
위의 두 단계 중 정확히 하나라도 파생된 System.Attribute
형식이 발생하는 경우 해당 형식은 attribute_name 결과입니다. 그렇지 않으면 컴파일 시간 오류가 발생합니다.
예: 이 접미사를 사용 또는 사용하지 않고 특성 클래스를 찾을 경우 모호성이 있으며 컴파일 시간 오류가 발생합니다. 가장 오른쪽에 있는 식별자가 축자 식별자(§6.4.3)가 되도록 attribute_name 철자가 지정되면 접미사가 없는 특성만 일치하므로 이러한 모호성을 확인할 수 있습니다. 예제
[AttributeUsage(AttributeTargets.All)] public class Example : Attribute {} [AttributeUsage(AttributeTargets.All)] public class ExampleAttribute : Attribute {} [Example] // Error: ambiguity class Class1 {} [ExampleAttribute] // Refers to ExampleAttribute class Class2 {} [@Example] // Refers to Example class Class3 {} [@ExampleAttribute] // Refers to ExampleAttribute class Class4 {}
는 명명
Example
된 두 개의 특성 클래스와ExampleAttribute
.를 보여 줍니다. 특성[Example]
은 둘 중 하나Example
또는ExampleAttribute
을 참조할 수 있으므로 모호합니다. 축자 식별자를 사용하면 이러한 드문 경우에서 정확한 의도를 지정할 수 있습니다. 특성[ExampleAttribute]
이 모호하지 않습니다(!이라는ExampleAttributeAttribute
특성 클래스가 있는 경우). 클래스Example
에 대한 선언이 제거되면 두 특성 모두 다음과 같이 명명된ExampleAttribute
특성 클래스를 참조합니다.[AttributeUsage(AttributeTargets.All)] public class ExampleAttribute : Attribute {} [Example] // Refers to ExampleAttribute class Class1 {} [ExampleAttribute] // Refers to ExampleAttribute class Class2 {} [@Example] // Error: no attribute named “Example” class Class3 {}
끝 예제
동일한 엔터티에서 일회용 특성 클래스를 두 번 이상 사용하는 것은 컴파일 시간 오류입니다.
예: 예제
[AttributeUsage(AttributeTargets.Class)] public class HelpStringAttribute : Attribute { public HelpStringAttribute(string value) { Value = value; } public string Value { get; } } [HelpString("Description of Class1")] [HelpString("Another description of Class1")] // multiple uses not allowed public class Class1 {}
는 단일 사용 특성 클래스인 사용을
HelpString
시도하기 때문에 컴파일 시간 오류가 발생하며 선언 시Class1
두 번 이상 발생합니다.끝 예제
다음 명령문이 모두 true이면 식 E
은 attribute_argument_expression.
- 형식
E
은 특성 매개 변수 형식(§22.2.4)입니다. - 컴파일 시간에 값
E
은 다음 중 하나로 확인할 수 있습니다.- 상수 값입니다.
-
System.Type
제네릭이 아닌 형식, 닫힌 생성 형식(§8.4.3) 또는 언바운드 제네릭 형식(§8.4.4)을 지정하는 typeof_expression(§12.8.18)를 사용하여 가져온 개체이지만 열린 형식(§8.4.3)은 아닙니다. - attribute_argument_expression1차원 배열입니다.
예제:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Field)] public class TestAttribute : Attribute { public int P1 { get; set; } public Type P2 { get; set; } public object P3 { get; set; } } [Test(P1 = 1234, P3 = new int[]{1, 3, 5}, P2 = typeof(float))] class MyClass {} class C<T> { [Test(P2 = typeof(T))] // Error – T not a closed type. int x1; [Test(P2 = typeof(C<T>))] // Error – C<;T>; not a closed type. int x2; [Test(P2 = typeof(C<int>))] // Ok int x3; [Test(P2 = typeof(C<>))] // Ok int x4; }
끝 예제
여러 부분으로 선언된 형식의 특성은 각 파트의 특성을 지정되지 않은 순서로 결합하여 결정됩니다. 동일한 특성이 여러 부분에 배치되는 경우 해당 특성을 형식에 여러 번 지정하는 것과 같습니다.
예: 두 부분:
[Attr1, Attr2("hello")] partial class A {} [Attr3, Attr2("goodbye")] partial class A {}
는 다음 단일 선언과 동일합니다.
[Attr1, Attr2("hello"), Attr3, Attr2("goodbye")] class A {}
끝 예제
형식 매개 변수의 특성은 동일한 방식으로 결합됩니다.
22.4 특성 인스턴스
22.4.1 일반
특성 인스턴스는 런타임에 특성을 나타내는 인스턴스입니다. 특성은 특성 클래스, 위치 인수 및 명명된 인수로 정의됩니다. 특성 인스턴스는 위치 및 명명된 인수를 사용하여 초기화되는 특성 클래스의 인스턴스입니다.
특성 인스턴스 검색에는 다음 하위 클래스에 설명된 대로 컴파일 시간 및 런타임 처리가 모두 포함됩니다.
22.4.2 특성 컴파일
특성 클래스, positional_argument_list, named_argument_listT
P
및 프로그램 엔터티 에 지정된 특성N
컴파일은 다음 단계를 통해 어셈블리 E
로 컴파일됩니다.A
- 새 양식의 object_creation_expression
T(P)
위한 컴파일 시간 처리 단계를 따릅니다. 이러한 단계를 수행하면 컴파일 시간 오류가 발생하거나 런타임에C
호출할 수 있는 인스턴스 생성자를T
결정합니다. - 공용 접근성이 없으면
C
컴파일 시간 오류가 발생합니다. - 각 named_argument
Arg
:N
-
Name
Arg
. -
Name
는 비정적 읽기-쓰기 공용 필드 또는 속성을 식별해야 합니다T
. 이러한 필드나 속성이 없으면T
컴파일 시간 오류가 발생합니다.
-
- positional_argument_list 내의 값이나 named_argument_list
P
N
의 값 중 하나가 형식System.String
이고 값이 유니코드 표준에 정의된 대로 잘 구성되지 않은 경우 컴파일된 값이 검색된 런타임 값(§22.4.3)과 같은지 여부를 구현으로 정의합니다.참고: 예를 들어 높은 서로게이트 UTF-16 코드 단위가 포함된 문자열은 바로 뒤에 낮은 서로게이트 코드 단위가 뒤따르는 것이 좋지 않습니다. 끝 메모
- 특성 클래스
T
, 인스턴스 생성C
자, positional_argument_list, named_argument_listT
P
E
다음 정보(특성의 런타임 인스턴스화용)를 저장하고 컴파일 시간에 값이 완전히 확인됩니다.
22.4.3 특성 인스턴스의 런타임 검색
§22.4.2에 정의된 용어를 사용하여 다음 단계를 사용하여 런타임에 T
C
어셈블리 P
에서 , , 및 N
연결된 E
특성 인스턴스를 검색할 수 있습니다.A
- 컴파일 시간에 결정된
C
실행하기 위한 런타임 처리 단계를 따릅니다. 이러한 단계는 예외를 발생시키거나 인스턴스를O
생성합니다T
. - 각 named_argument
Arg
N
순서대로:-
Name
Arg
. 비정적 공용 읽기/쓰기 필드 또는 속성을Name
식별하지 않으면O
예외가 throw됩니다. -
Value
의 attribute_argument_expressionArg
한 결과입니다. - 필드를
Name
식별하는 경우O
이 필드를Value
.로 설정합니다. - 그렇지 않으면 Name은 .에
O
대한 속성을 식별합니다. 이 속성을 Value로 설정합니다. - 결과는
O
positional_argument_list 및 named_argument_listT
사용하여 초기화된 특성 클래스P
의N
인스턴스입니다.
-
참고: 저장에
T
대 한 형식 ,C
,P
N
(및 연결E
) 에A
지정 하 고 검색E
하는T
메커니즘,C
P
N
에서A
(따라서 런타임에 특성 인스턴스를 가져오는 방법) 이 사양의 범위를 벗어날 수 있습니다. 끝 메모
예제: CLI
Help
구현에서는 §22.2.3에서 예제 프로그램을 컴파일하여 만든 어셈블리의 특성 인스턴스를 다음 프로그램으로 검색할 수 있습니다.public sealed class InterrogateHelpUrls { public static void Main(string[] args) { Type helpType = typeof(HelpAttribute); string assemblyName = args[0]; foreach (Type t in Assembly.Load(assemblyName).GetTypes()) { Console.WriteLine($"Type : {t}"); var attributes = t.GetCustomAttributes(helpType, false); var helpers = (HelpAttribute[]) attributes; foreach (var helper in helpers) { Console.WriteLine($"\tUrl : {helper.Url}"); } } } }
끝 예제
22.5 예약 특성
22.5.1 일반
다양한 특성이 언어에 어떤 식으로든 영향을 미칩니다. 이러한 특성은 다음과 같습니다.
-
System.AttributeUsageAttribute
(§22.5.2) 특성 클래스를 사용할 수 있는 방법을 설명하는 데 사용됩니다. -
System.Diagnostics.ConditionalAttribute
(§22.5.3)는 조건부 메서드 및 조건부 특성 클래스를 정의하는 데 사용되는 다중 사용 특성 클래스입니다. 이 특성은 조건부 컴파일 기호를 테스트하여 조건을 나타냅니다. -
System.ObsoleteAttribute
(§22.5.4), 멤버를 사용되지 않는 것으로 표시하는 데 사용됩니다. -
System.Runtime.CompilerServices.AsyncMethodBuilderAttribute
(§22.5.5), 비동기 메서드에 대한 작업 작성기를 설정하는 데 사용됩니다. -
System.Runtime.CompilerServices.CallerLineNumberAttribute
(§22.5.6.2),System.Runtime.CompilerServices.CallerFilePathAttribute
(§22.5.6.3) 및System.Runtime.CompilerServices.CallerMemberNameAttribute
(§22.5.6.4) - 호출 컨텍스트에 대한 정보를 선택적 매개 변수에 제공하는 데 사용됩니다.
Nullable 정적 분석 특성(§22.5.7)은 nullabilities 및 null 상태에 대해 생성된 경고의 정확성을 향상시킬 수 있습니다(§8.9.5).
실행 환경에서는 C# 프로그램의 실행에 영향을 주는 추가 구현 정의 특성을 제공할 수 있습니다.
22.5.2 AttributeUsage 특성
이 특성 AttributeUsage
은 특성 클래스를 사용할 수 있는 방식을 설명하는 데 사용됩니다.
특성으로 AttributeUsage
데코레이팅된 클래스는 직접 또는 간접적으로 파생 System.Attribute
되어야합니다. 그렇지 않으면 컴파일 타임 오류가 발생합니다.
참고: 이 특성을 사용하는 예제는 §22.2.2를 참조하세요. 끝 메모
22.5.3 조건부 특성
22.5.3.1 일반
이 특성 Conditional
은 조건부 메서드 및 조건부 특성 클래스의 정의를 사용하도록 설정합니다.
22.5.3.2 조건부 메서드
특성으로 Conditional
데코레이트된 메서드는 조건부 메서드입니다. 따라서 각 조건부 메서드는 특성 Conditional
에 선언된 조건부 컴파일 기호와 연결됩니다.
예제:
class Eg { [Conditional("ALPHA")] [Conditional("BETA")] public static void M() { // ... } }
는
Eg.M
두 조건부 컴파일 기호와 연결된 조건부 메서드로 선언합니다ALPHA
.BETA
끝 예제
조건부 메서드에 대한 호출은 호출 시점에 연결된 조건부 컴파일 기호 중 하나 이상이 정의된 경우 포함되며, 그렇지 않으면 호출이 생략됩니다.
조건부 메서드에는 다음과 같은 제한 사항이 적용됩니다.
- 조건부 메서드는 class_declaration 또는 struct_declaration 메서드여야 합니다. 인터페이스 선언의 메서드에 특성을 지정하면
Conditional
컴파일 시간 오류가 발생합니다. - 조건부 메서드에는 반환 형식
void
이 있어야 합니다. - 조건부 메서드는 한정자와 함께
override
표시되지 않습니다. 그러나 조건부 메서드는 한정자를 사용하여virtual
표시할 수 있습니다. 이러한 메서드의 재정의는 암시적으로 조건부이며 특성으로Conditional
명시적으로 표시되지 않습니다. - 조건부 메서드는 인터페이스 메서드의 구현이 아니어야 합니다. 그렇지 않으면 컴파일 타임 오류가 발생합니다.
- 조건부 메서드의 매개 변수는 출력 매개 변수가 아니어야 합니다.
또한 조건부 메서드에서 대리자를 만들면 컴파일 시간 오류가 발생합니다.
예: 예제
#define DEBUG using System; using System.Diagnostics; class Class1 { [Conditional("DEBUG")] public static void M() { Console.WriteLine("Executed Class1.M"); } } class Class2 { public static void Test() { Class1.M(); } }
는 조건부 메서드로 선언합니다
Class1.M
.Class2
'sTest
메서드는 이 메서드를 호출합니다. 조건부 컴파일 기호DEBUG
가 정의되므로 호출되면Class2.Test
호출M
됩니다. 기호DEBUG
가 정의Class2.Test
되지 않은 경우 호출하지 않습니다Class1.M
.끝 예제
조건부 메서드에 대한 호출의 포함 또는 제외는 호출 지점에서 조건부 컴파일 기호에 의해 제어된다는 것을 이해하는 것이 중요합니다.
예제: 다음 코드에서
// File Class1.cs: using System; using System.Diagnostics; class Class1 { [Conditional("DEBUG")] public static void F() { Console.WriteLine("Executed Class1.F"); } } // File Class2.cs: #define DEBUG class Class2 { public static void G() { Class1.F(); // F is called } } // File Class3.cs: #undef DEBUG class Class3 { public static void H() { Class1.F(); // F is not called } }
클래스와
Class2
Class3
각 클래스는 조건부 메서드Class1.F
에 대한 호출을 포함하며 정의 여부에DEBUG
따라 조건부입니다. 이 기호는 컨텍스트Class2
에서 정의되지만 정의되지 않으므로Class3
inF
에 대한Class2
호출은 포함되지만 in에 대한F
Class3
호출은 생략됩니다.끝 예제
상속 체인에서 조건부 메서드를 사용하는 것은 혼동될 수 있습니다. 형식base
을 통해 base.M
조건부 메서드를 호출하는 경우 일반적인 조건부 메서드 호출 규칙이 적용됩니다.
예제: 다음 코드에서
// File Class1.cs using System; using System.Diagnostics; class Class1 { [Conditional("DEBUG")] public virtual void M() => Console.WriteLine("Class1.M executed"); } // File Class2.cs class Class2 : Class1 { public override void M() { Console.WriteLine("Class2.M executed"); base.M(); // base.M is not called! } } // File Class3.cs #define DEBUG class Class3 { public static void Main() { Class2 c = new Class2(); c.M(); // M is called } }
Class2
에는 기본 클래스에M
정의된 호출이 포함됩니다. 기본 메서드는 정의되지 않은 기호DEBUG
의 존재에 따라 조건부이므로 이 호출은 생략됩니다. 따라서 메서드는 콘솔 "Class2.M executed
"에만 씁니다. pp_declaration의 현명한 사용은 이러한 문제를 제거 할 수 있습니다.끝 예제
22.5.3.3 조건부 특성 클래스
하나 이상의 특성으로 데코레이팅된 특성 클래스(Conditional
)는 조건부 특성 클래스입니다. 따라서 조건부 특성 클래스는 해당 Conditional
특성에 선언된 조건부 컴파일 기호와 연결됩니다.
예제:
[Conditional("ALPHA")] [Conditional("BETA")] public class TestAttribute : Attribute {}
는
TestAttribute
조건부 컴파일 기호와 연결된 조건부 특성 클래스로 선언합니다ALPHA
BETA
.끝 예제
조건부 특성의 특성 사양(§22.3)은 지정된 시점에 연결된 조건부 컴파일 기호 중 하나 이상이 정의된 경우 포함되며, 그렇지 않으면 특성 사양을 생략합니다.
조건부 특성 클래스의 특성 사양을 포함하거나 제외하는 것은 사양의 시점에서 조건부 컴파일 기호에 의해 제어됩니다.
예: 예제에서
// File Test.cs: using System; using System.Diagnostics; [Conditional("DEBUG")] public class TestAttribute : Attribute {} // File Class1.cs: #define DEBUG [Test] // TestAttribute is specified class Class1 {} // File Class2.cs: #undef DEBUG [Test] // TestAttribute is not specified class Class2 {}
클래스는
Class1
Class2
정의 여부에Test
따라 조건부인 특성DEBUG
으로 데코레이팅됩니다. 이 기호는 컨텍스트Class1
에서 정의되지만 정의되지 않으므로Class2
테스트 특성Class1
의 사양은 포함되지만 특성의 사양Test
Class2
은 생략됩니다.끝 예제
22.5.4 사용되지 않는 특성
이 특성 Obsolete
은 더 이상 사용해서는 안 되는 형식의 형식 및 멤버를 표시하는 데 사용됩니다.
프로그램에서 Obsolete
특성으로 데코레이팅된 형식 또는 멤버를 사용하는 경우 컴파일러는 경고 또는 오류를 발생합니다. 특히 오류 매개 변수가 제공되지 않거나 오류 매개 변수가 제공되고 값이 false
경우 컴파일러에서 경고를 발생합니다. 오류 매개 변수가 지정되고 값이 true
경우 컴파일러에서 오류를 발생합니다.
예제: 다음 코드에서
[Obsolete("This class is obsolete; use class B instead")] class A { public void F() {} } class B { public void F() {} } class Test { static void Main() { A a = new A(); // Warning a.F(); } }
클래스
A
는 특성으로 데코Obsolete
레이팅됩니다. 이 클래스를A
사용할Main
때마다 "이 클래스는 사용되지 않습니다. 대신 클래스B
를 사용합니다."끝 예제
22.5.5 AsyncMethodBuilder 특성
이 특성은 §15.15.1에 설명되어 있습니다.
22.5.6 호출자 정보 특성
22.5.6.1 일반
로깅 및 보고와 같은 목적을 위해 함수 멤버가 호출 코드에 대한 특정 컴파일 시간 정보를 가져오는 것이 유용할 수 있습니다. 호출자 정보 특성은 이러한 정보를 투명하게 전달하는 방법을 제공합니다.
선택적 매개 변수에 호출자 정보 특성 중 하나로 주석이 추가된 경우 호출에서 해당 인수를 생략한다고 해서 반드시 기본 매개 변수 값이 대체되는 것은 아닙니다. 대신 호출 컨텍스트에 대한 지정된 정보를 사용할 수 있는 경우 해당 정보가 인수 값으로 전달됩니다.
예제:
public void Log( [CallerLineNumber] int line = -1, [CallerFilePath] string path = null, [CallerMemberName] string name = null ) { Console.WriteLine((line < 0) ? "No line" : "Line "+ line); Console.WriteLine((path == null) ? "No file path" : path); Console.WriteLine((name == null) ? "No member name" : name); }
인수가 없는 호출
Log()
은 호출의 줄 번호와 파일 경로뿐만 아니라 호출이 발생한 멤버의 이름을 출력합니다.끝 예제
호출자 정보 특성은 대리자 선언을 포함하여 어디서나 선택적 매개 변수에서 발생할 수 있습니다. 그러나 특정 호출자 정보 특성은 특성이 될 수 있는 매개 변수의 형식에 제한이 있으므로 대체된 값에서 매개 변수 형식으로의 암시적 변환이 항상 존재합니다.
부분 메서드 선언의 정의 및 구현 부분 모두의 매개 변수에 동일한 호출자 정보 특성을 갖는 것은 오류입니다. 정의 파트의 호출자 정보 특성만 적용되는 반면 구현 파트에서만 발생하는 호출자 정보 특성은 무시됩니다.
호출자 정보는 오버로드 확인에 영향을 주지 않습니다. 특성이 지정된 선택적 매개 변수는 여전히 호출자의 소스 코드에서 생략되므로 오버로드 확인은 생략된 다른 선택적 매개 변수(§12.6.4)를 무시하는 것과 같은 방식으로 해당 매개 변수를 무시합니다.
호출자 정보는 함수가 소스 코드에서 명시적으로 호출되는 경우에만 대체됩니다. 암시적 부모 생성자 호출과 같은 암시적 호출에는 원본 위치가 없으며 호출자 정보를 대체하지 않습니다. 또한 동적으로 바인딩된 호출은 호출자 정보를 대체하지 않습니다. 이러한 경우 호출자 정보 특성 매개 변수를 생략하면 매개 변수의 지정된 기본값이 대신 사용됩니다.
한 가지 예외는 쿼리 식입니다. 이러한 확장은 구문 확장으로 간주되며 호출자가 확장하여 호출자 정보 특성이 있는 선택적 매개 변수를 생략하는 경우 호출자 정보가 대체됩니다. 사용되는 위치는 호출이 생성된 쿼리 절의 위치입니다.
지정된 매개 변수에 둘 이상의 호출자-정보 특성이 지정된 경우 다음 순서CallerLineNumber
CallerFilePath
CallerMemberName
로 인식됩니다. 다음 매개 변수 선언을 고려합니다.
[CallerMemberName, CallerFilePath, CallerLineNumber] object p = ...
CallerLineNumber
는 우선적으로 적용되고 다른 두 특성은 무시됩니다. 생략 CallerLineNumber
된 경우 CallerFilePath
우선 순위가 적용되며 CallerMemberName
무시됩니다. 이러한 특성의 어휘 순서는 관련이 없습니다.
22.5.6.2 CallerLineNumber 특성
상수 값 System.Runtime.CompilerServices.CallerLineNumberAttribute
에서 매개 변수 형식으로의 표준 암시적 변환(§10.4.2)이 있는 경우 선택적 매개 변수에 특성 int.MaxValue
이 허용됩니다. 이렇게 하면 해당 값까지 음수가 아닌 줄 번호를 오류 없이 전달할 수 있습니다.
소스 코드의 위치에서 함수 호출이 선택적 매개 변수를 CallerLineNumberAttribute
생략하는 경우 해당 위치의 줄 번호를 나타내는 숫자 리터럴이 기본 매개 변수 값 대신 호출에 대한 인수로 사용됩니다.
호출이 여러 줄에 걸쳐 있는 경우 선택한 줄은 구현에 따라 달라집니다.
줄 번호는 지시문(#line
)의 영향을 받을 수 있습니다.
22.5.6.3 CallerFilePath 특성
매개 변수 형식으로의 표준 암시적 변환(System.Runtime.CompilerServices.CallerFilePathAttribute
)이 있는 경우 선택적 매개 변수에 특성 string
이 허용됩니다.
소스 코드의 위치에서 함수 호출이 선택적 매개 변수를 CallerFilePathAttribute
생략하는 경우 해당 위치의 파일 경로를 나타내는 문자열 리터럴이 기본 매개 변수 값 대신 호출에 대한 인수로 사용됩니다.
파일 경로의 형식은 구현에 따라 다릅니다.
파일 경로는 지시문(#line
)의 영향을 받을 수 있습니다.
22.5.6.4 CallerMemberName 특성
매개 변수 형식으로의 표준 암시적 변환(System.Runtime.CompilerServices.CallerMemberNameAttribute
)이 있는 경우 선택적 매개 변수에 특성 string
이 허용됩니다.
함수 멤버의 본문 내 위치 또는 함수 멤버 자체 또는 해당 반환 형식에 적용된 특성 내의 함수 호출이 소스 코드의 매개 변수 또는 형식 매개 변수에서 선택적 매개 변수 CallerMemberNameAttribute
를 생략하는 경우 해당 멤버의 이름을 나타내는 문자열 리터럴이 기본 매개 변수 값 대신 호출에 대한 인수로 사용됩니다.
제네릭 메서드 내에서 발생하는 호출의 경우 형식 매개 변수 목록 없이 메서드 이름 자체만 사용됩니다.
명시적 인터페이스 멤버 구현 내에서 발생하는 호출의 경우 이전 인터페이스 자격 없이 메서드 이름 자체만 사용됩니다.
속성 또는 이벤트 접근자 내에서 발생하는 호출의 경우 사용된 멤버 이름은 속성 또는 이벤트 자체의 이름입니다.
인덱서 접근자 내에서 발생하는 호출의 경우 사용되는 멤버 이름은 인덱서 멤버(있는 경우)에서 (IndexerNameAttribute
)에 의해 제공되거나, 그렇지 않으면 기본 이름 Item
입니다.
필드 또는 이벤트 이니셜라이저 내에서 발생하는 호출의 경우 사용되는 멤버 이름은 초기화되는 필드 또는 이벤트의 이름입니다.
인스턴스 생성자, 정적 생성자, 종료자 및 연산자의 선언 내에서 발생하는 호출의 경우 사용된 멤버 이름은 구현에 따라 다릅니다.
22.5.7 코드 분석 특성
22.5.7.1 일반
이 섹션의 특성은 null 허용 여부 및 null 상태 진단(§8.9.5)을 제공하는 컴파일러를 지원하기 위한 추가 정보를 제공하는 데 사용됩니다. 컴파일러는 null 상태 진단을 수행할 필요가 없습니다. 이러한 특성의 존재 또는 부재는 언어나 프로그램의 동작에 영향을 미치지 않습니다. null 상태 진단을 제공하지 않는 컴파일러는 이러한 특성의 존재를 읽고 무시해야 합니다. null 상태 진단을 제공하는 컴파일러는 진단을 알리는 데 사용하는 이러한 특성에 대해 이 섹션에 정의된 의미를 사용해야 합니다.
코드 분석 특성은 네임스페이스에 System.Diagnostics.CodeAnalysis
선언됩니다.
Attribute | 의미 |
---|---|
AllowNull (§22.5.7.2) |
null을 허용하지 않는 인수는 null일 수 있습니다. |
DisallowNull (§22.5.7.3) |
null 허용 인수는 null이 아니어야 합니다. |
MaybeNull (§22.5.7.6) |
null을 허용하지 않는 반환 값은 null일 수 있습니다. |
NotNull (§22.5.7.8) |
null 허용 반환 값은 null이 아닙니다. |
MaybeNullWhen (§22.5.7.7) |
메서드가 지정된 bool 값을 반환하는 경우 null을 허용하지 않는 인수는 null일 수 있습니다. |
NotNullWhen (§22.5.7.10) |
메서드가 지정된 bool 값을 반환하는 경우 nullable 인수는 null이 아닙니다. |
NotNullIfNotNull (§22.5.7.9) |
지정된 매개 변수의 인수가 null이 아닌 경우 반환 값은 null이 아닙니다. |
DoesNotReturn (§22.5.7.4) |
이 메서드는 반환되지 않습니다. |
DoesNotReturnIf (§22.5.7.5) |
연결된 bool 매개 변수에 지정된 값이 있는 경우 이 메서드는 값을 반환하지 않습니다. |
§22.5.7.1의 다음 섹션은 조건부로 규범적입니다.
22.5.7.2 AllowNull 특성
해당 형식에서 허용하지 않는 경우에도 null 값을 입력으로 허용하도록 지정합니다.
예: 적절한 기본값이 있으므로 반환
null
되지 않는 다음 읽기/쓰기 속성을 고려합니다. 그러나 사용자는 set 접근자에 null을 제공하여 속성을 해당 기본값으로 설정할 수 있습니다.#nullable enable public class X { [AllowNull] public string ScreenName { get => _screenName; set => _screenName = value ?? GenerateRandomScreenName(); } private string _screenName = GenerateRandomScreenName(); private static string GenerateRandomScreenName() => ...; }
해당 속성의 set 접근자를 다음과 같은 용도로 사용하는 경우
var v = new X(); v.ScreenName = null; // may warn without attribute AllowNull
특성이 없으면 nullable 형식이 아닌 속성이 null 값으로 설정된 것처럼 보이기 때문에 컴파일러가 경고를 생성할 수 있습니다. 특성이 있으면 해당 경고가 표시되지 않습니다. 끝 예제
22.5.7.3 DisallowNull 특성
해당 형식에서 허용하는 경우에도 null 값이 입력으로 허용되지 않도록 지정합니다.
예: null이 기본값이지만 클라이언트는 null이 아닌 값으로만 설정할 수 있는 다음 속성을 고려합니다.
#nullable enable public class X { [DisallowNull] public string? ReviewComment { get => _comment; set => _comment = value ?? throw new ArgumentNullException(nameof(value), "Cannot set to null"); } private string? _comment = default; }
get 접근자는
null
기본값을 반환할 수 있으므로 컴파일러는 액세스하기 전에 확인해야 한다는 경고를 표시할 수 있습니다. 또한 호출자에게 null일 수 있더라도 호출자가 명시적으로 null로 설정해서는 안 된다고 경고합니다. 끝 예제
22.5.7.4 DoesNotReturn 특성
지정된 메서드가 반환되지 않도록 지정합니다.
예: 다음을 고려합니다.
public class X { [DoesNotReturn] private void FailFast() => throw new InvalidOperationException(); public void SetState(object? containedField) { if ((!isInitialized) || (containedField == null)) { FailFast(); } // null check not needed. _field = containedField; } private bool isInitialized = false; private object _field; }
특성이 있으면 여러 가지 방법으로 컴파일러에 도움이 됩니다. 먼저 메서드가 예외를 throw하지 않고 종료할 수 있는 경로가 있는 경우 컴파일러에서 경고를 실행할 수 있습니다. 둘째, 컴파일러는 적절한 catch 절이 발견될 때까지 해당 메서드를 호출한 후 코드에서 nullable 경고를 표시하지 않을 수 있습니다. 셋째, 연결할 수 없는 코드는 null 상태에 영향을 주지 않습니다.
특성은 이 특성의 존재 여부에 따라 연결 가능성(§13.2) 또는 명확한 할당(§9.4) 분석을 변경하지 않습니다. Null 허용 여부 경고에만 영향을 줍니다. 끝 예제
22.5.7.5 DoesNotReturnIf 특성
연결된 bool
매개 변수에 지정된 값이 있으면 지정된 메서드가 반환되지 않도록 지정합니다.
예: 다음을 고려합니다.
#nullable enable public class X { private void ThrowIfNull([DoesNotReturnIf(true)] bool isNull, string argumentName) { if (!isNull) { throw new ArgumentException(argumentName, $"argument {argumentName} can't be null"); } } public void SetFieldState(object containedField) { ThrowIfNull(containedField == null, nameof(containedField)); // unreachable code when "isInitialized" is false: _field = containedField; } private bool isInitialized = false; private object _field = default!; }
끝 예제
22.5.7.6 MaybeNull 특성
nullable이 아닌 반환 값이 null일 수 있음을 지정합니다.
예제: 다음 제네릭 메서드를 고려합니다.
#nullable enable public T? Find<T>(IEnumerable<T> sequence, Func<T, bool> predicate) { ... }
이 코드의 개념은 대체되는
T
string
경우T?
null 허용 주석이 된다는 것입니다. 그러나 참조 형식으로 제한되지 않으므로 이 코드는 유효T
하지 않습니다. 그러나 이 특성을 추가하면 문제가 해결됩니다.#nullable enable [return: MaybeNull] public T Find<T>(IEnumerable<T> sequence, Func<T, bool> predicate) { ... }
이 특성은 계약이 nullable이 아닌 형식을 의미하지만 반환 값은 실제로
null
있을 수 있음을 호출자에게 알릴 수 있습니다. 끝 예제
22.5.7.7 MaybeNullWhen 특성
메서드가 지정된 null
값을 반환할 때 nullable이 아닌 인수가 될 bool
수 있도록 지정합니다. 이는 특성(MaybeNull
)과 유사 하지만 지정된 반환 값에 대한 매개 변수를 포함합니다.
22.5.7.8 NotNull 특성
메서드가 throw하지 않고 반환하는 null
경우 null 허용 값이 절대로 반환되지 않도록 지정합니다.
예: 다음을 고려합니다.
#nullable enable public static void ThrowWhenNull([NotNull] object? value, string valueExpression = "") => _ = value ?? throw new ArgumentNullException(valueExpression); public static void LogMessage(string? message) { ThrowWhenNull(message, nameof(message)); Console.WriteLine(message.Length); }
null 참조 형식을 사용하도록 설정하면 메서드
ThrowWhenNull
는 경고 없이 컴파일됩니다. 해당 메서드가 반환될value
때 인수는 그렇지 않습니다null
. 그러나 null 참조를 사용하여 호출ThrowWhenNull
할 수 있습니다. 끝 예제
22.5.7.9 NotNullIfNotNull 특성
지정된 매개 변수에 대한 인수가 아닌 null
경우 반환 값이 아닌 null
지 지정합니다.
예: 반환 값의 null 상태는 하나 이상의 인수의 null 상태에 따라 달라질 수 있습니다. 특정 인수가
null
않을 때 메서드가 항상 null이 아닌 값을 반환할 때 컴파일러의 분석을 지원하기 위해NotNullIfNotNull
특성을 사용할 수 있습니다. 다음 태그를 살펴봅니다.#nullable enable string GetTopLevelDomainFromFullUrl(string url) { ... }
인수가
url
아닌null
null
경우 반환되지 않습니다. Null 허용 참조를 사용하도록 설정하면 API가 null 인수를 허용하지 않는 한 해당 서명이 올바르게 작동합니다. 그러나 인수가 null일 수 있으면 반환 값도 null일 수 있습니다. 해당 계약을 올바르게 표현하려면 다음과 같이 이 메서드에 주석을 추가합니다.#nullable enable [return: NotNullIfNotNull("url")] string? GetTopLevelDomainFromFullUrl(string? url) { ... }
끝 예제
22.5.7.10 NotNullWhen 특성
메서드가 지정된 null
값을 반환할 bool
때 nullable 인수가 되지 않도록 지정합니다.
예: 인수 또는 빈 문자열일 때 라이브러리 메서드
String.IsNullOrEmpty(String)
가 반환true
됩니다null
. null-check의 한 형태입니다. 메서드가 반환false
되는 경우 호출자는 인수를 null로 확인할 필요가 없습니다. 이 nullable과 같은 메서드를 인식하려면 매개 변수 형식을 nullable 참조 형식으로 만들고 NotNullWhen 특성을 추가합니다.#nullable enable bool IsNullOrEmpty([NotNullWhen(false)] string? value) { ... }
끝 예제
22.6 상호 운용에 대한 특성
다른 언어와의 상호 운용을 위해 인덱싱된 속성을 사용하여 인덱서가 구현될 수 있습니다. 인덱서에 대한 특성이 없 IndexerName
으면 기본적으로 이름이 Item
사용됩니다. 이 IndexerName
특성을 사용하면 개발자가 이 기본값을 재정의하고 다른 이름을 지정할 수 있습니다.
예: 기본적으로 인덱서의 이름은 .입니다
Item
. 다음과 같이 재정의할 수 있습니다.[System.Runtime.CompilerServices.IndexerName("TheItem")] public int this[int index] { get { ... } set { ... } }
이제 인덱서의 이름은 .입니다
TheItem
.끝 예제
ECMA C# draft specification