표현식Expressions

식은 연산자와 피연산자의 시퀀스입니다.An expression is a sequence of operators and operands. 이 장에서는 구문, 피연산자 및 연산자의 계산 순서와 식의 의미를 정의 합니다.This chapter defines the syntax, order of evaluation of operands and operators, and meaning of expressions.

식 분류Expression classifications

식은 다음 중 하나로 분류됩니다.An expression is classified as one of the following:

  • 값입니다.A value. 모든 값에는 연결된 형식이 있습니다.Every value has an associated type.
  • 변수입니다.A variable. 모든 변수에는 연결 된 형식, 즉 변수의 선언 된 형식이 있습니다.Every variable has an associated type, namely the declared type of the variable.
  • 네임스페이스입니다.A namespace. 이 분류를 사용 하는 식은 member_access (멤버 액세스)의 왼쪽 으로만 표시 될 수 있습니다.An expression with this classification can only appear as the left hand side of a member_access (Member access). 다른 모든 컨텍스트에서는 네임 스페이스로 분류 된 식으로 인해 컴파일 시간 오류가 발생 합니다.In any other context, an expression classified as a namespace causes a compile-time error.
  • 형식입니다.A type. 이 분류를 사용 하는 식은 member_access 의 왼쪽 (멤버 액세스) 또는 as 연산자 (as 연산자), is 연산자 (is 연산자) 또는 @no에 대 한 피연산자로만 나타날 수 있습니다. __a-6 연산자 (typeof 연산자)An expression with this classification can only appear as the left hand side of a member_access (Member access), or as an operand for the as operator (The as operator), the is operator (The is operator), or the typeof operator (The typeof operator). 다른 컨텍스트에서 형식으로 분류 된 식은 컴파일 시간 오류를 발생 시킵니다.In any other context, an expression classified as a type causes a compile-time error.
  • 멤버 조회 (멤버 조회)로 인해 발생 하는 오버 로드 된 메서드의 집합인 메서드 그룹입니다.A method group, which is a set of overloaded methods resulting from a member lookup (Member lookup). 메서드 그룹에는 연결 된 인스턴스 식과 연결 된 형식 인수 목록이 있을 수 있습니다.A method group may have an associated instance expression and an associated type argument list. 인스턴스 메서드가 호출 되 면 인스턴스 식의 계산 결과는 this (이 액세스)으로 표시 되는 인스턴스가 됩니다.When an instance method is invoked, the result of evaluating the instance expression becomes the instance represented by this (This access). 메서드 그룹은 invocation_expression (호출 식), delegate_creation_expression (대리자 생성 식) 및 is 연산자의 왼쪽으로 사용할 수 있으며, 암시적으로 사용할 수 있습니다. 호환 되는 대리자 형식 (메서드 그룹 변환)으로 변환 됩니다.A method group is permitted in an invocation_expression (Invocation expressions) , a delegate_creation_expression (Delegate creation expressions) and as the left hand side of an is operator, and can be implicitly converted to a compatible delegate type (Method group conversions). 다른 컨텍스트에서는 메서드 그룹으로 분류 된 식으로 인해 컴파일 시간 오류가 발생 합니다.In any other context, an expression classified as a method group causes a compile-time error.
  • Null 리터럴입니다.A null literal. 이 분류를 사용 하는 식은 참조 형식 또는 nullable 형식으로 암시적으로 변환 될 수 있습니다.An expression with this classification can be implicitly converted to a reference type or nullable type.
  • 익명 함수입니다.An anonymous function. 이 분류를 사용 하는 식은 호환 되는 대리자 형식이 나 식 트리 형식으로 암시적으로 변환 될 수 있습니다.An expression with this classification can be implicitly converted to a compatible delegate type or expression tree type.
  • 속성 액세스입니다.A property access. 모든 속성 액세스에는 연결 된 형식, 즉 속성 형식이 있습니다.Every property access has an associated type, namely the type of the property. 또한 속성 액세스에는 연결 된 인스턴스 식이 있을 수 있습니다.Furthermore, a property access may have an associated instance expression. 인스턴스 속성 액세스의 접근자 (get 또는 set 블록)가 호출 되 면 인스턴스 식의 평가 결과가 this (이 액세스)로 표시 되는 인스턴스가 됩니다.When an accessor (the get or set block) of an instance property access is invoked, the result of evaluating the instance expression becomes the instance represented by this (This access).
  • 이벤트 액세스입니다.An event access. 모든 이벤트 액세스에는 연결 된 형식, 즉 이벤트 형식이 있습니다.Every event access has an associated type, namely the type of the event. 또한 이벤트 액세스에는 연결 된 인스턴스 식이 있을 수 있습니다.Furthermore, an event access may have an associated instance expression. 이벤트 액세스는 +=-= 연산자 (이벤트 할당)의 왼쪽 피연산자로 표시 될 수 있습니다.An event access may appear as the left hand operand of the += and -= operators (Event assignment). 다른 컨텍스트에서는 이벤트 액세스로 분류 된 식으로 인해 컴파일 시간 오류가 발생 합니다.In any other context, an expression classified as an event access causes a compile-time error.
  • 인덱서 액세스입니다.An indexer access. 모든 인덱서 액세스에는 연결 된 형식, 즉 인덱서의 요소 형식이 있습니다.Every indexer access has an associated type, namely the element type of the indexer. 또한 인덱서 액세스에는 연결 된 인스턴스 식과 관련 된 인수 목록이 있습니다.Furthermore, an indexer access has an associated instance expression and an associated argument list. 인덱서 액세스의 접근자 (get 또는 set 블록)를 호출 하는 경우 인스턴스 식의 계산 결과는 this (이 액세스)로 표시 되는 인스턴스가 되며 인수 목록을 평가한 결과는가 됩니다. 호출의 매개 변수 목록입니다.When an accessor (the get or set block) of an indexer access is invoked, the result of evaluating the instance expression becomes the instance represented by this (This access), and the result of evaluating the argument list becomes the parameter list of the invocation.
  • 없는지.Nothing. 이는 식이 반환 형식이 void 인 메서드를 호출 하는 경우에 발생 합니다.This occurs when the expression is an invocation of a method with a return type of void. Nothing으로 분류 된 식은 statement_expression (식 문)의 컨텍스트에서만 유효 합니다.An expression classified as nothing is only valid in the context of a statement_expression (Expression statements).

식의 최종 결과는 네임 스페이스, 형식, 메서드 그룹 또는 이벤트 액세스 일 수 없습니다.The final result of an expression is never a namespace, type, method group, or event access. 위에서 설명한 것 처럼 이러한 식의 범주는 특정 컨텍스트에서만 허용 되는 중간 구문입니다.Rather, as noted above, these categories of expressions are intermediate constructs that are only permitted in certain contexts.

속성 액세스 또는 인덱서 액세스는 get 접근자 또는 set 접근자를 호출 하 여 항상 값으로 다시 분류할 됩니다.A property access or indexer access is always reclassified as a value by performing an invocation of the get accessor or the set accessor. 특정 접근자는 속성 또는 인덱서 액세스의 컨텍스트에 의해 결정 됩니다. 액세스 권한이 할당의 대상인 경우 set 접근자 를 호출 하 여 새 값 (단순 할당)을 할당 합니다.The particular accessor is determined by the context of the property or indexer access: If the access is the target of an assignment, the set accessor is invoked to assign a new value (Simple assignment). 그렇지 않으면 get 접근자 를 호출 하 여 현재 값 (식의 값)을 가져옵니다.Otherwise, the get accessor is invoked to obtain the current value (Values of expressions).

식의 값Values of expressions

식에 포함 된 대부분의 구문은 궁극적으로 식에서 을 표시 해야 합니다.Most of the constructs that involve an expression ultimately require the expression to denote a value. 이러한 경우 실제 식이 네임 스페이스, 형식, 메서드 그룹 또는 nothing을 나타내는 경우 컴파일 타임 오류가 발생 합니다.In such cases, if the actual expression denotes a namespace, a type, a method group, or nothing, a compile-time error occurs. 그러나 식이 속성 액세스, 인덱서 액세스 또는 변수를 나타내는 경우 속성, 인덱서 또는 변수의 값은 암시적으로 대체 됩니다.However, if the expression denotes a property access, an indexer access, or a variable, the value of the property, indexer, or variable is implicitly substituted:

  • 변수의 값은 변수에 의해 식별 되는 저장소 위치에 현재 저장 된 값입니다.The value of a variable is simply the value currently stored in the storage location identified by the variable. 변수는 값을 얻을 수 있을 때까지 명확 하게 할당 된것으로 간주 해야 합니다. 그렇지 않으면 컴파일 시간 오류가 발생 합니다.A variable must be considered definitely assigned (Definite assignment) before its value can be obtained, or otherwise a compile-time error occurs.
  • 속성 액세스 식의 값은 속성의 get 접근자 를 호출 하 여 가져옵니다.The value of a property access expression is obtained by invoking the get accessor of the property. 속성에 get 접근자가 없는 경우 컴파일 타임 오류가 발생 합니다.If the property has no get accessor, a compile-time error occurs. 그렇지 않으면 함수 멤버 호출 (동적 오버 로드 확인의 컴파일 타임 확인)이 수행 되 고 호출 결과가 속성 액세스 식의 값이 됩니다.Otherwise, a function member invocation (Compile-time checking of dynamic overload resolution) is performed, and the result of the invocation becomes the value of the property access expression.
  • 인덱서 액세스 식의 값은 인덱서의 get 접근자 를 호출 하 여 가져옵니다.The value of an indexer access expression is obtained by invoking the get accessor of the indexer. 인덱서에 get 접근자가 없는 경우 컴파일 타임 오류가 발생 합니다.If the indexer has no get accessor, a compile-time error occurs. 그렇지 않으면 함수 멤버 호출 (동적 오버 로드 확인의 컴파일 시간 검사)이 인덱서 액세스 식과 연결 된 인수 목록을 사용 하 여 수행 되며, 호출 결과는 인덱서 액세스의 값이 됩니다. 식.Otherwise, a function member invocation (Compile-time checking of dynamic overload resolution) is performed with the argument list associated with the indexer access expression, and the result of the invocation becomes the value of the indexer access expression.

정적 및 동적 바인딩Static and Dynamic Binding

구성 식의 형식 또는 값 (인수, 피연산자, 수신자)을 기반으로 하는 작업의 의미를 결정 하는 프로세스를 종종 바인딩이라고 합니다.The process of determining the meaning of an operation based on the type or value of constituent expressions (arguments, operands, receivers) is often referred to as binding. 예를 들어, 메서드 호출의 의미는 수신자 및 인수의 형식에 따라 결정 됩니다.For instance the meaning of a method call is determined based on the type of the receiver and arguments. 연산자의 의미는 해당 피연산자의 형식에 따라 결정 됩니다.The meaning of an operator is determined based on the type of its operands.

C# 작업의 의미는 일반적으로 컴파일 시간에 해당 구성 요소의 컴파일 시간 형식에 따라 결정 됩니다.In C# the meaning of an operation is usually determined at compile-time, based on the compile-time type of its constituent expressions. 마찬가지로 식에 오류가 있는 경우 컴파일러에서 오류를 검색 하 여 보고 합니다.Likewise, if an expression contains an error, the error is detected and reported by the compiler. 이 방법을 정적 바인딩이라고 합니다.This approach is known as static binding.

그러나 식이 동적 식 인 경우 (예: dynamic 형식)이는 해당 형식이 참여 하는 모든 바인딩이 런타임 형식을 기반으로 해야 함을 나타냅니다. 즉, 런타임에는 런타임에 표시 되는 개체의 실제 형식입니다. 컴파일 시간입니다.However, if an expression is a dynamic expression (i.e. has the type dynamic) this indicates that any binding that it participates in should be based on its run-time type (i.e. the actual type of the object it denotes at run-time) rather than the type it has at compile-time. 따라서 이러한 작업의 바인딩은 프로그램이 실행 되는 동안 작업이 실행 되는 시간까지 지연 됩니다.The binding of such an operation is therefore deferred until the time where the operation is to be executed during the running of the program. 이를 동적 바인딩이라고 합니다.This is referred to as dynamic binding.

작업을 동적으로 바인딩하는 경우에는 컴파일러에서 검사를 거의 수행 하지 않습니다.When an operation is dynamically bound, little or no checking is performed by the compiler. 런타임 바인딩이 실패 하면 런타임 시 오류가 예외로 보고 됩니다.Instead if the run-time binding fails, errors are reported as exceptions at run-time.

에서 C# 다음 작업은 바인딩이 적용 됩니다.The following operations in C# are subject to binding:

  • 멤버 액세스: e.MMember access: e.M
  • 메서드 호출: e.M(e1, ..., eN)Method invocation: e.M(e1, ..., eN)
  • 대리자 호출: e(e1, ..., eN)Delegate invocation:e(e1, ..., eN)
  • 요소 액세스: e[e1, ..., eN]Element access: e[e1, ..., eN]
  • 개체 만들기: new C(e1, ..., eN)Object creation: new C(e1, ..., eN)
  • 오버 로드 된 단항 연산자: +, -, !, ~, ++, --, true, falseOverloaded unary operators: +, -, !, ~, ++, --, true, false
  • 오버 로드 된 이항 연산자: +, -, *, /, @no__t, &, &&, |, ||, ??, 0, 1, 2, 3, 4, 5, 6, 7, 8Overloaded binary operators: +, -, *, /, %, &, &&, |, ||, ??, ^, <<, >>, ==,!=, >, <, >=, <=
  • 할당 연산자: =, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, 0Assignment operators: =, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=
  • 암시적 변환과 명시적 변환Implicit and explicit conversions

동적 식이 포함 되지 않은 경우는 C# 기본적으로 정적 바인딩으로 사용 됩니다 .이는 구성 식의 컴파일 타임 형식이 선택 프로세스에서 사용 됨을 의미 합니다.When no dynamic expressions are involved, C# defaults to static binding, which means that the compile-time types of constituent expressions are used in the selection process. 그러나 위에 나열 된 작업의 구성 식 중 하나가 동적 식인 경우에는 작업이 동적으로 바인딩됩니다.However, when one of the constituent expressions in the operations listed above is a dynamic expression, the operation is instead dynamically bound.

바인딩 시간Binding-time

정적 바인딩은 컴파일 시간에 발생 하는 반면 동적 바인딩은 런타임에 발생 합니다.Static binding takes place at compile-time, whereas dynamic binding takes place at run-time. 다음 섹션에서 바인딩 시간 이라는 용어는 바인딩이 발생 하는 시기에 따라 컴파일 시간 또는 런타임을 참조 합니다.In the following sections, the term binding-time refers to either compile-time or run-time, depending on when the binding takes place.

다음 예제에서는 정적 및 동적 바인딩과 바인딩 시간을 개념 하는 방법을 보여 줍니다.The following example illustrates the notions of static and dynamic binding and of binding-time:

object  o = 5;
dynamic d = 5;

Console.WriteLine(5);  // static  binding to Console.WriteLine(int)
Console.WriteLine(o);  // static  binding to Console.WriteLine(object)
Console.WriteLine(d);  // dynamic binding to Console.WriteLine(int)

처음 두 호출은 정적으로 바인딩됩니다. Console.WriteLine의 오버 로드는 해당 인수의 컴파일 시간 형식에 따라 선택 됩니다.The first two calls are statically bound: the overload of Console.WriteLine is picked based on the compile-time type of their argument. 따라서 바인딩 시간은 컴파일 시간입니다.Thus, the binding-time is compile-time.

세 번째 호출은 동적으로 바인딩됩니다. Console.WriteLine의 오버 로드는 인수의 런타임 형식에 따라 선택 됩니다.The third call is dynamically bound: the overload of Console.WriteLine is picked based on the run-time type of its argument. 이는 인수가 동적 식 이기 때문에 발생 합니다. 컴파일 시간 형식은 dynamic입니다.This happens because the argument is a dynamic expression -- its compile-time type is dynamic. 따라서 세 번째 호출에 대 한 바인딩 시간은 런타임입니다.Thus, the binding-time for the third call is run-time.

동적 바인딩Dynamic binding

동적 바인딩의 목적은 프로그램에서 동적 개체와 C# 상호 작용할 수 있도록 하는 것입니다. 즉, C# 형식 시스템의 일반 규칙을 따르지 않는 개체입니다.The purpose of dynamic binding is to allow C# programs to interact with dynamic objects, i.e. objects that do not follow the normal rules of the C# type system. 동적 개체는 다른 형식의 시스템을 사용 하는 다른 프로그래밍 언어의 개체 일 수도 있고, 다른 작업에 대해 고유한 바인딩 의미 체계를 구현 하기 위해 프로그래밍 방식으로 설정 되는 개체 일 수도 있습니다.Dynamic objects may be objects from other programming languages with different types systems, or they may be objects that are programmatically setup to implement their own binding semantics for different operations.

동적 개체가 고유한 의미 체계를 구현 하는 메커니즘은 정의 된 구현입니다.The mechanism by which a dynamic object implements its own semantics is implementation defined. 지정 된 인터페이스-즉, 정의 된 다시 구현은 동적 개체에서 구현 되어 특수 한 의미 C# 체계가 있음을 런타임에 알립니다.A given interface -- again implementation defined -- is implemented by dynamic objects to signal to the C# run-time that they have special semantics. 따라서 동적 개체에 대 한 작업이 동적으로 바인딩될 때마다이 문서에 지정 된 C# 것과는 다른 고유한 바인딩 의미 체계를 사용 합니다.Thus, whenever operations on a dynamic object are dynamically bound, their own binding semantics, rather than those of C# as specified in this document, take over.

동적 바인딩의 목적은 동적 개체와의 상호 운용을 허용 하는 것 이지만 C# 가 동적 개체 인지 여부에 관계 없이 모든 개체에 대 한 동적 바인딩을 허용 합니다.While the purpose of dynamic binding is to allow interoperation with dynamic objects, C# allows dynamic binding on all objects, whether they are dynamic or not. 이렇게 하면 동적 개체에 대 한 작업의 결과가 동적 개체가 아닌 경우에도 컴파일 타임에 프로그래머에 게 알 수 없는 형식이 될 수 있으므로 동적 개체의 원활한 통합이 가능 합니다.This allows for a smoother integration of dynamic objects, as the results of operations on them may not themselves be dynamic objects, but are still of a type unknown to the programmer at compile-time. 또한 동적 바인딩은 관련 된 개체가 없는 경우에도 오류가 발생 하기 쉬운 리플렉션 기반 코드를 제거 하는 데 도움이 됩니다.Also dynamic binding can help eliminate error-prone reflection-based code even when no objects involved are dynamic objects.

다음 섹션에서는 동적 바인딩이 적용 될 때의 각 구문에 대해 정확히 설명 하 고, 컴파일 시간 검사 (있는 경우) 및 컴파일 시간 결과와 식 분류에 대해 설명 합니다.The following sections describe for each construct in the language exactly when dynamic binding is applied, what compile time checking -- if any -- is applied, and what the compile-time result and expression classification is.

구성 식 형식Types of constituent expressions

작업이 정적으로 바인딩될 때 구성 식의 형식 (예: 받는 사람, 인수, 인덱스 또는 피연산자)은 항상 해당 식의 컴파일 타임 형식으로 간주 됩니다.When an operation is statically bound, the type of a constituent expression (e.g. a receiver, an argument, an index or an operand) is always considered to be the compile-time type of that expression.

작업이 동적으로 바인딩될 때 구성 식의 형식은 구성 식의 컴파일 타임 형식에 따라 다양 한 방법으로 결정 됩니다.When an operation is dynamically bound, the type of a constituent expression is determined in different ways depending on the compile-time type of the constituent expression:

  • 컴파일 시간 형식의 구성 식 dynamic은 런타임에 식이 계산 되는 실제 값의 형식을 갖는 것으로 간주 됩니다.A constituent expression of compile-time type dynamic is considered to have the type of the actual value that the expression evaluates to at runtime
  • 컴파일 시간 형식이 형식 매개 변수 인 구성 식은 런타임에 형식 매개 변수가 바인딩된 형식으로 간주 됩니다.A constituent expression whose compile-time type is a type parameter is considered to have the type which the type parameter is bound to at runtime
  • 그렇지 않으면 구성 식의 컴파일 타임 형식이 포함 된 것으로 간주 됩니다.Otherwise the constituent expression is considered to have its compile-time type.

연산자Operators

식은 피연산자연산자에서 생성 됩니다.Expressions are constructed from operands and operators. 식의 연산자는 피연산자에 적용할 연산을 나타냅니다.The operators of an expression indicate which operations to apply to the operands. 연산자의 예로 +, -, *, /new가 있습니다.Examples of operators include +, -, *, /, and new. 피연산자의 예로는 리터럴, 필드, 지역 변수 및 식이 있습니다.Examples of operands include literals, fields, local variables, and expressions.

연산자에는 다음과 같은 세 종류가 있습니다.There are three kinds of operators:

  • 단항 연산자.Unary operators. 단항 연산자는 하나의 피연산자를 사용 하 고 접두사 표기법 (예: --x) 또는 후 위 표기법 (예: x++)을 사용 합니다.The unary operators take one operand and use either prefix notation (such as --x) or postfix notation (such as x++).
  • 이항 연산자.Binary operators. 이항 연산자는 두 개의 피연산자를 사용 하며, 모두 중 위 표기법을 사용 합니다 (예: x + y).The binary operators take two operands and all use infix notation (such as x + y).
  • 삼진 연산자입니다.Ternary operator. @No__t-0 인 삼항 연산자는 하나만 존재 합니다. 세 개의 피연산자를 사용 하 고 중 위 표기법 (c ? x : y)을 사용 합니다.Only one ternary operator, ?:, exists; it takes three operands and uses infix notation (c ? x : y).

식에서 연산자의 계산 순서는 연산자의 우선 순위결합성 (연산자 우선 순위 및 결합성)에 따라 결정 됩니다.The order of evaluation of operators in an expression is determined by the precedence and associativity of the operators (Operator precedence and associativity).

식의 피연산자는 왼쪽에서 오른쪽으로 계산 됩니다.Operands in an expression are evaluated from left to right. 예를 들어 F(i) + G(i++) * H(i)에서 메서드 @no__t은 i의 이전 값을 사용 하 여 호출 되 고, 메서드 Gi의 이전 값을 사용 하 여 호출 되 고, 마지막으로 i의 새 값을 사용 하 여 메서드 @no__t가 호출 됩니다.For example, in F(i) + G(i++) * H(i), method F is called using the old value of i, then method G is called with the old value of i, and, finally, method H is called with the new value of i. 이는 연산자 우선 순위와는 별개입니다.This is separate from and unrelated to operator precedence.

특정 연산자는 오버로드할 수 있습니다.Certain operators can be overloaded. 연산자 오버 로드를 사용 하면 피연산자 중 하나 또는 둘 모두가 사용자 정의 클래스 또는 구조체 형식 (연산자 오버 로드) 인 작업에 대해 사용자 정의 연산자 구현을 지정할 수 있습니다.Operator overloading permits user-defined operator implementations to be specified for operations where one or both of the operands are of a user-defined class or struct type (Operator overloading).

연산자 우선 순위 및 결합성Operator precedence and associativity

식에 여러 연산자가 포함되어 있으면 연산자의 우선 순위에 따라 개별 연산자가 계산되는 순서가 제어됩니다.When an expression contains multiple operators, the precedence of the operators controls the order in which the individual operators are evaluated. 예를 들어 * 연산자는 이진 + 연산자 보다 우선 순위가 높기 때문에 x + y * z 식은 x + (y * z)로 계산 됩니다.For example, the expression x + y * z is evaluated as x + (y * z) because the * operator has higher precedence than the binary + operator. 연산자의 우선 순위는 관련 된 문법 프로덕션의 정의에 의해 설정 됩니다.The precedence of an operator is established by the definition of its associated grammar production. 예를 들어, additive_expression+ 또는 - 연산자로 구분 된 일련의 multiplicative_expression으로 구성 되므로 +- 연산자는 *, / 및 @no__ 보다 낮은 우선 순위를 제공 합니다. t-8 연산자.For example, an additive_expression consists of a sequence of multiplicative_expressions separated by + or - operators, thus giving the + and - operators lower precedence than the *, /, and % operators.

다음 표에서는 모든 연산자의 우선 순위를 내림차순으로 요약 합니다.The following table summarizes all operators in order of precedence from highest to lowest:

섹션Section 범주Category 연산자Operators
기본 식Primary expressions Primary x.y f(x) a[x] x++ x-- new typeof default checked unchecked delegatex.y f(x) a[x] x++ x-- new typeof default checked unchecked delegate
단항 연산자Unary operators 단항Unary + - ! ~ ++x --x (T)x+ - ! ~ ++x --x (T)x
산술 연산자Arithmetic operators 곱하기Multiplicative * / %* / %
산술 연산자Arithmetic operators 더하기Additive + -+ -
시프트 연산자Shift operators ShiftShift << >><< >>
관계형 및 형식 테스트 연산자Relational and type-testing operators 관계형 및 형식 테스트Relational and type testing < > <= >= is as< > <= >= is as
관계형 및 형식 테스트 연산자Relational and type-testing operators 같음Equality == !=== !=
논리 연산자Logical operators 논리적 ANDLogical AND &
논리 연산자Logical operators 논리 XORLogical XOR ^
논리 연산자Logical operators 논리적 ORLogical OR |
조건부 논리 연산자Conditional logical operators 조건부 ANDConditional AND &&
조건부 논리 연산자Conditional logical operators 조건부 ORConditional OR ||
Null 결합 연산자The null coalescing operator Null 결합Null coalescing ??
조건 연산자Conditional operator 조건Conditional ?:
대입 연산자, 익명 함수 식Assignment operators, Anonymous function expressions 할당 및 람다 식Assignment and lambda expression = *= /= %= += -= <<= >>= &= ^= |= =>= *= /= %= += -= <<= >>= &= ^= |= =>

동일한 우선 순위를 가진 두 연산자 사이에 피연산자가 나타날 경우 연산자의 결합성은 연산이 수행 되는 순서를 제어 합니다.When an operand occurs between two operators with the same precedence, the associativity of the operators controls the order in which the operations are performed:

  • 대입 연산자와 null 병합 연산자를 제외 하 고 모든 이항 연산자는 왼쪽에서 오른쪽으로 수행 됩니다. 즉, 작업은 왼쪽에서 오른쪽으로 수행 됩니다.Except for the assignment operators and the null coalescing operator, all binary operators are left-associative, meaning that operations are performed from left to right. 예를 들어, x + y + z(x + y) + z로 계산됩니다.For example, x + y + z is evaluated as (x + y) + z.
  • 대입 연산자, null 병합 연산자 및 조건 연산자 (?:)는 오른쪽 결합성이며,이는 오른쪽에서 왼쪽으로 연산이 수행 됨을 의미 합니다.The assignment operators, the null coalescing operator and the conditional operator (?:) are right-associative, meaning that operations are performed from right to left. 예를 들어, x = y = zx = (y = z)로 계산됩니다.For example, x = y = z is evaluated as x = (y = z).

우선 순위 및 결합성은 괄호를 사용하여 제어할 수 있습니다.Precedence and associativity can be controlled using parentheses. 예를 들어 x + y * z는 먼저 yz를 곱한 다음 그 결과를 x와 더하지만 (x + y) * z는 먼저 xy를 더한 다음 그 결과에 z를 곱합니다.For example, x + y * z first multiplies y by z and then adds the result to x, but (x + y) * z first adds x and y and then multiplies the result by z.

연산자 오버로드Operator overloading

모든 단항 및 이항 연산자에는 식에서 자동으로 사용할 수 있는 미리 정의 된 구현이 있습니다.All unary and binary operators have predefined implementations that are automatically available in any expression. 미리 정의 된 구현 외에도 클래스 및 구조체 (연산자)에 operator 선언을 포함 하 여 사용자 정의 구현을 도입할 수 있습니다.In addition to the predefined implementations, user-defined implementations can be introduced by including operator declarations in classes and structs (Operators). 사용자 정의 연산자 구현은 항상 미리 정의 된 연산자 구현 보다 우선적으로 적용 됩니다. 해당 하는 사용자 정의 연산자 구현이 없는 경우에만 단항 연산자 오버 로드 확인이항 연산자 오버 로드 확인에 설명 된 대로 미리 정의 된 연산자 구현을 고려 합니다.User-defined operator implementations always take precedence over predefined operator implementations: Only when no applicable user-defined operator implementations exist will the predefined operator implementations be considered, as described in Unary operator overload resolution and Binary operator overload resolution.

오버 로드할 수 있는 단항 연산자 는 다음과 같습니다.The overloadable unary operators are:

+   -   !   ~   ++   --   true   false

@No__t-0 및 false은 식에서 명시적으로 사용 되지 않으므로 연산자 우선 순위 및 결합성의 우선 순위 테이블에는 포함 되지 않지만 여러 식에서 호출 되기 때문에 연산자로 간주 됩니다. 컨텍스트: 부울 식 (부울 식) 및 조건부 (조건부연산자)와 조건부 논리 연산자 (조건부 논리 연산자)를 포함 하는 식입니다.Although true and false are not used explicitly in expressions (and therefore are not included in the precedence table in Operator precedence and associativity), they are considered operators because they are invoked in several expression contexts: boolean expressions (Boolean expressions) and expressions involving the conditional (Conditional operator), and conditional logical operators (Conditional logical operators).

오버 로드할 수 있는 이항 연산자 는 다음과 같습니다.The overloadable binary operators are:

+   -   *   /   %   &   |   ^   <<   >>   ==   !=   >   <   >=   <=

위에 나열 된 연산자만 오버 로드 될 수 있습니다.Only the operators listed above can be overloaded. 특히 멤버 액세스, 메서드 호출 또는 = &&, ||, ??, ?:, =>, checked, unchecked, new, typeof, 2 연산자를 오버 로드할 수 없습니다.In particular, it is not possible to overload member access, method invocation, or the =, &&, ||, ??, ?:, =>, checked, unchecked, new, typeof, default, as, and is operators.

이항 연산자가 오버로드되면 해당 대입 연산자도 암시적으로 오버로드됩니다.When a binary operator is overloaded, the corresponding assignment operator, if any, is also implicitly overloaded. 예를 들어 @no__t 연산자의 오버 로드는-1 @no__t 연산자의 오버 로드 이기도 합니다.For example, an overload of operator * is also an overload of operator *=. 이는 복합 할당에 추가로 설명 되어 있습니다.This is described further in Compound assignment. 할당 연산자 자체 (=)를 오버 로드할 수 없습니다.Note that the assignment operator itself (=) cannot be overloaded. 할당은 항상 변수에 대 한 간단한 비트 단위 복사를 수행 합니다.An assignment always performs a simple bit-wise copy of a value into a variable.

@No__t-0과 같은 캐스트 연산은 사용자 정의 변환 (사용자 정의 변환)을 제공 하 여 오버 로드 됩니다.Cast operations, such as (T)x, are overloaded by providing user-defined conversions (User-defined conversions).

@No__t-0과 같은 요소 액세스는 오버 로드 가능한 연산자로 간주 되지 않습니다.Element access, such as a[x], is not considered an overloadable operator. 대신 인덱서 (인덱서)를 통해 사용자 정의 인덱싱이 지원 됩니다.Instead, user-defined indexing is supported through indexers (Indexers).

식에서 연산자는 연산자 표기법을 사용 하 여 참조 되 고, 선언에서 연산자는 함수 표기법을 사용 하 여 참조 됩니다.In expressions, operators are referenced using operator notation, and in declarations, operators are referenced using functional notation. 다음 표에서는 단항 연산자와 이항 연산자에 대 한 연산자와 함수 표기법 간의 관계를 보여 줍니다.The following table shows the relationship between operator and functional notations for unary and binary operators. 첫 번째 항목에서 op 는 오버 로드 가능한 단항 전위 연산자를 나타냅니다.In the first entry, op denotes any overloadable unary prefix operator. 두 번째 항목에서 op 는 단항 후 위 ++-- 연산자를 나타냅니다.In the second entry, op denotes the unary postfix ++ and -- operators. 세 번째 항목에서 op 는 오버 로드 가능한 이항 연산자를 나타냅니다.In the third entry, op denotes any overloadable binary operator.

연산자 표기법Operator notation 함수 표기법Functional notation
op x operator op(x)
x op operator op(x)
x op y operator op(x,y)

사용자 정의 연산자 선언에는 항상 연산자 선언이 포함 된 클래스 또는 구조체 형식으로 매개 변수를 하나 이상 사용 해야 합니다.User-defined operator declarations always require at least one of the parameters to be of the class or struct type that contains the operator declaration. 따라서 사용자 정의 연산자가 미리 정의 된 연산자와 동일한 서명을 사용 하는 것은 불가능 합니다.Thus, it is not possible for a user-defined operator to have the same signature as a predefined operator.

사용자 정의 연산자 선언은 연산자의 구문, 우선 순위 또는 결합성을 수정할 수 없습니다.User-defined operator declarations cannot modify the syntax, precedence, or associativity of an operator. 예를 들어 / 연산자는 항상 이항 연산자 이며, 항상 연산자 우선 순위 및 결합성에 지정 된 우선 순위 수준을 가지 며 항상 왼쪽 결합성이 있습니다.For example, the / operator is always a binary operator, always has the precedence level specified in Operator precedence and associativity, and is always left-associative.

사용자 정의 연산자가 pleases 계산을 수행할 수 있지만, 직관적으로 예상 되는 결과를 생성 하는 구현은 사용 하지 않는 것이 좋습니다.While it is possible for a user-defined operator to perform any computation it pleases, implementations that produce results other than those that are intuitively expected are strongly discouraged. 예를 들어 operator ==의 구현은 두 피연산자가 같은지 비교 하 여 적절 한 bool 결과를 반환 해야 합니다.For example, an implementation of operator == should compare the two operands for equality and return an appropriate bool result.

조건부 논리 연산자 를 통한 기본 식 의 개별 연산자에 대 한 설명은 미리 정의 된 연산자 구현 및 각 연산자에 적용 되는 모든 추가 규칙을 지정 합니다.The descriptions of individual operators in Primary expressions through Conditional logical operators specify the predefined implementations of the operators and any additional rules that apply to each operator. 설명은 단항 연산자 오버 로드 확인, 이진 연산자 오버 로드 확인숫자 수준 올리기를 사용 합니다 .이에 대 한 정의는 다음 섹션에 나와 있습니다.The descriptions make use of the terms unary operator overload resolution, binary operator overload resolution, and numeric promotion, definitions of which are found in the following sections.

단항 연산자 오버 로드 확인Unary operator overload resolution

-0 또는 x op @no__t 폼의 작업입니다. 여기서 op는 오버 로드할 수 있는 단항 연산자이 고 xX 형식의 식인 경우 다음과 같이 처리 됩니다.An operation of the form op x or x op, where op is an overloadable unary operator, and x is an expression of type X, is processed as follows:

  • 작업 operator op(x)X에서 제공 하는 후보 사용자 정의 연산자 집합은 후보 사용자 정의 연산자의 규칙을 사용 하 여 결정 됩니다.The set of candidate user-defined operators provided by X for the operation operator op(x) is determined using the rules of Candidate user-defined operators.
  • 후보 사용자 정의 연산자 집합이 비어 있지 않으면이는 작업의 후보 연산자 집합이 됩니다.If the set of candidate user-defined operators is not empty, then this becomes the set of candidate operators for the operation. 그렇지 않은 경우에는 리프트 된 형태를 포함 하 여 미리 정의 된 단항 operator op 구현이 작업의 후보 연산자 집합이 됩니다.Otherwise, the predefined unary operator op implementations, including their lifted forms, become the set of candidate operators for the operation. 지정 된 연산자의 미리 정의 된 구현은 연산자 (기본 식단항 연산자)의 설명에 지정 됩니다.The predefined implementations of a given operator are specified in the description of the operator (Primary expressions and Unary operators).
  • 오버 로드 확인의 오버 로드 확인 규칙은 후보 연산자 집합에 적용 되어 인수 목록과 관련 하 여 가장 적합 한 연산자 ((x))를 선택 하 고이 연산자는 오버 로드 확인 프로세스의 결과가 됩니다.The overload resolution rules of Overload resolution are applied to the set of candidate operators to select the best operator with respect to the argument list (x), and this operator becomes the result of the overload resolution process. 오버 로드 확인이 단일 최적 연산자를 선택 하지 못하면 바인딩 시간 오류가 발생 합니다.If overload resolution fails to select a single best operator, a binding-time error occurs.

이항 연산자 오버 로드 확인Binary operator overload resolution

@No__t-0 형식의 작업 (op은 오버 로드할 수 있는 이항 연산자이 고, xX 형식의 식이고, y는 다음과 같이 처리 됩니다.An operation of the form x op y, where op is an overloadable binary operator, x is an expression of type X, and y is an expression of type Y, is processed as follows:

  • @No__t-@no__t 0에 의해 제공 되는 후보 사용자 정의 연산자 집합 operator op(x,y))가 결정 됩니다.The set of candidate user-defined operators provided by X and Y for the operation operator op(x,y) is determined. 집합은 X에서 제공 하는 후보 연산자의 합집합과 Y에서 제공 하는 후보 연산자의 합집합으로 구성 되며 각각 후보 사용자 정의 연산자의 규칙을 사용 하 여 결정 됩니다.The set consists of the union of the candidate operators provided by X and the candidate operators provided by Y, each determined using the rules of Candidate user-defined operators. @No__t-0과 Y이 같은 형식이 면이 고, XY이 공통 기본 형식에서 파생 되는 경우 공유 후보 연산자는 결합 된 설정 에서만 발생 합니다.If X and Y are the same type, or if X and Y are derived from a common base type, then shared candidate operators only occur in the combined set once.
  • 후보 사용자 정의 연산자 집합이 비어 있지 않으면이는 작업의 후보 연산자 집합이 됩니다.If the set of candidate user-defined operators is not empty, then this becomes the set of candidate operators for the operation. 그렇지 않으면 리프트 된 형태를 포함 하 여 미리 정의 된 이항 operator op 구현이 작업의 후보 연산자 집합이 됩니다.Otherwise, the predefined binary operator op implementations, including their lifted forms, become the set of candidate operators for the operation. 지정 된 연산자의 미리 정의 된 구현은 연산자 ( 조건부 논리 연산자를 통한산술 연산자 )의 설명에 지정 됩니다.The predefined implementations of a given operator are specified in the description of the operator (Arithmetic operators through Conditional logical operators). 미리 정의 된 열거형 및 대리자 연산자의 경우 피연산자 중 하나의 바인딩 시간 형식인 enum 또는 대리자 형식으로 정의 된 연산자만 고려 됩니다.For predefined enum and delegate operators, the only operators considered are those defined by an enum or delegate type that is the binding-time type of one of the operands.
  • 오버 로드 확인의 오버 로드 확인 규칙은 후보 연산자 집합에 적용 되어 인수 목록과 관련 하 여 가장 적합 한 연산자 ((x,y))를 선택 하 고이 연산자는 오버 로드 확인 프로세스의 결과가 됩니다.The overload resolution rules of Overload resolution are applied to the set of candidate operators to select the best operator with respect to the argument list (x,y), and this operator becomes the result of the overload resolution process. 오버 로드 확인이 단일 최적 연산자를 선택 하지 못하면 바인딩 시간 오류가 발생 합니다.If overload resolution fails to select a single best operator, a binding-time error occurs.

후보 사용자 정의 연산자Candidate user-defined operators

@No__t-0을 지정 하 고 작업 operator op(A)을 지정 합니다. 여기서 op는 오버 로드할 수 있는 연산자이 고 A은 인수 목록입니다. operator op(A)에 대 한 T에서 제공 하는 후보 사용자 정의 연산자 집합은 다음과 같이 결정 됩니다.Given a type T and an operation operator op(A), where op is an overloadable operator and A is an argument list, the set of candidate user-defined operators provided by T for operator op(A) is determined as follows:

  • @No__t-0 유형을 확인 합니다.Determine the type T0. @No__t-0이 nullable 형식이 면-1 @no__t 기본 형식이 고, 그렇지 @no__t 않으면-2는 T과 같습니다.If T is a nullable type, T0 is its underlying type, otherwise T0 is equal to T.
  • @No__t-1의 모든 operator op 선언과 이러한 연산자의 모든 리프트 된 형태 (해당 하는함수 멤버)에 대 한 인수 목록 A에 대 한 연산자가 적용 되는 경우 후보 연산자 집합은 모두로 구성 됩니다. T0에서 적용 가능한 연산자.For all operator op declarations in T0 and all lifted forms of such operators, if at least one operator is applicable (Applicable function member) with respect to the argument list A, then the set of candidate operators consists of all such applicable operators in T0.
  • 그렇지 않고 T0 object 이면 후보 연산자 집합이 비어 있습니다.Otherwise, if T0 is object, the set of candidate operators is empty.
  • 그렇지 않으면 T0에서 제공 하는 후보 연산자 집합이 T0의 직접 기본 클래스에서 제공 하는 후보 연산자 집합 또는 T0이 형식 매개 변수인 경우 T0의 유효한 기본 클래스입니다.Otherwise, the set of candidate operators provided by T0 is the set of candidate operators provided by the direct base class of T0, or the effective base class of T0 if T0 is a type parameter.

숫자 승격Numeric promotions

숫자 수준 올리기는 미리 정의 된 단항 및 이항 숫자 연산자의 피연산자에 대 한 특정 암시적 변환을 자동으로 수행 하는 것으로 구성 됩니다.Numeric promotion consists of automatically performing certain implicit conversions of the operands of the predefined unary and binary numeric operators. 숫자 승격은 고유 메커니즘이 아니라 미리 정의 된 연산자에 오버 로드 확인을 적용 하는 효과입니다.Numeric promotion is not a distinct mechanism, but rather an effect of applying overload resolution to the predefined operators. 사용자 정의 연산자를 구현 하 여 비슷한 효과를 발생 시킬 수 있지만, 숫자 수준 올리기는 특히 사용자 정의 연산자의 평가에 영향을 주지 않습니다.Numeric promotion specifically does not affect evaluation of user-defined operators, although user-defined operators can be implemented to exhibit similar effects.

숫자 수준 올리기의 예로 이항 * 연산자의 미리 정의 된 구현을 고려해 보세요.As an example of numeric promotion, consider the predefined implementations of the binary * operator:

int operator *(int x, int y);
uint operator *(uint x, uint y);
long operator *(long x, long y);
ulong operator *(ulong x, ulong y);
float operator *(float x, float y);
double operator *(double x, double y);
decimal operator *(decimal x, decimal y);

이 연산자 집합에 오버 로드 확인 규칙 (오버 로드 확인)이 적용 되는 경우 피연산자 형식에서 암시적 변환이 있는 첫 번째 연산자를 선택 하는 것이 효과가 있습니다.When overload resolution rules (Overload resolution) are applied to this set of operators, the effect is to select the first of the operators for which implicit conversions exist from the operand types. 예를 들어 b * s (bbyte이 고 sshort 인 작업의 경우 오버 로드 확인은 가장 적합 한 연산자로 operator *(int,int)를 선택 합니다.For example, for the operation b * s, where b is a byte and s is a short, overload resolution selects operator *(int,int) as the best operator. 따라서 bsint로 변환 되 고 결과의 형식은-3 @no__t 됩니다.Thus, the effect is that b and s are converted to int, and the type of the result is int. 마찬가지로 i * d (iint이 고 ddouble 인 작업의 경우 오버 로드 확인은 가장 적합 한 연산자로 operator *(double,double)를 선택 합니다.Likewise, for the operation i * d, where i is an int and d is a double, overload resolution selects operator *(double,double) as the best operator.

단항 숫자 승격Unary numeric promotions

단항 숫자 프로 모션은 미리 정의 된 +, -~ 단항 연산자의 피연산자에 대해 발생 합니다.Unary numeric promotion occurs for the operands of the predefined +, -, and ~ unary operators. 단항 숫자 수준 올리기는 sbyte, byte, short, ushort 또는 char 형식의 피연산자를 int 형식으로 변환 하는 것으로 구성 됩니다.Unary numeric promotion simply consists of converting operands of type sbyte, byte, short, ushort, or char to type int. 또한 단항 - 연산자의 경우 단항 숫자 승격은 형식 uint 형식의 피연산자를 long 형식으로 변환 합니다.Additionally, for the unary - operator, unary numeric promotion converts operands of type uint to type long.

이진 숫자 프로 모션Binary numeric promotions

이진 숫자 수준 올리기는 미리 정의 된 +, -, *, /, %, &, |, ^, ==, !=, 0, 1, 3 이항 연산자의 피연산자에 대해 발생 합니다.Binary numeric promotion occurs for the operands of the predefined +, -, *, /, %, &, |, ^, ==, !=, >, <, >=, and <= binary operators. 이진 숫자 승격은 암시적으로 두 피연산자를 모두 일반 형식으로 변환 합니다 .이 형식은 비관계형 연산자의 경우에도 작업의 결과 형식이 됩니다.Binary numeric promotion implicitly converts both operands to a common type which, in case of the non-relational operators, also becomes the result type of the operation. 이진 숫자 수준 올리기는 여기에 표시 된 순서 대로 다음 규칙을 적용 하는 것으로 구성 됩니다.Binary numeric promotion consists of applying the following rules, in the order they appear here:

  • 피연산자 중 하나가 0 @no__t 형식인 경우 다른 피연산자는-1 @no__t 형식으로 변환 되 고 다른 피연산자가 float 또는 double 형식인 경우에는 바인딩 시간 오류가 발생 합니다.If either operand is of type decimal, the other operand is converted to type decimal, or a binding-time error occurs if the other operand is of type float or double.
  • 그렇지 않고 피연산자 중 하나가 0 @no__t 형식인 경우 다른 피연산자는-1 @no__t 형식으로 변환 됩니다.Otherwise, if either operand is of type double, the other operand is converted to type double.
  • 그렇지 않고 피연산자 중 하나가 0 @no__t 형식인 경우 다른 피연산자는-1 @no__t 형식으로 변환 됩니다.Otherwise, if either operand is of type float, the other operand is converted to type float.
  • 그렇지 않고 피연산자 중 하나가-0 @no__t 형식인 경우 다른 피연산자가-1 @no__t 형식으로 변환 되거나 다른 피연산자가 sbyte, short, int 또는 long 형식인 경우에는 바인딩 시간 오류가 발생 합니다.Otherwise, if either operand is of type ulong, the other operand is converted to type ulong, or a binding-time error occurs if the other operand is of type sbyte, short, int, or long.
  • 그렇지 않고 피연산자 중 하나가 0 @no__t 형식인 경우 다른 피연산자는-1 @no__t 형식으로 변환 됩니다.Otherwise, if either operand is of type long, the other operand is converted to type long.
  • 그렇지 않고 피연산자 중 하나가 0 @no__t 형식이 고 다른 피연산자가 sbyte, short 또는 int 형식인 경우 두 피연산자는 모두 long 형식으로 변환 됩니다.Otherwise, if either operand is of type uint and the other operand is of type sbyte, short, or int, both operands are converted to type long.
  • 그렇지 않고 피연산자 중 하나가 0 @no__t 형식인 경우 다른 피연산자는-1 @no__t 형식으로 변환 됩니다.Otherwise, if either operand is of type uint, the other operand is converted to type uint.
  • 그렇지 않으면 두 피연산자가 모두 int 형식으로 변환 됩니다.Otherwise, both operands are converted to type int.

첫 번째 규칙은 decimal 유형을 doublefloat 유형과 혼합 하는 작업을 허용 하지 않습니다.Note that the first rule disallows any operations that mix the decimal type with the double and float types. 이 규칙은 decimal 형식과 doublefloat 형식 간에 암시적 변환이 없음을 말합니다.The rule follows from the fact that there are no implicit conversions between the decimal type and the double and float types.

또한 피연산자는 부호 있는 정수 계열 형식인 경우에 ulong 형식일 수 없습니다.Also note that it is not possible for an operand to be of type ulong when the other operand is of a signed integral type. 그 이유는 부호 있는 정수 계열 형식 뿐만 아니라 ulong의 전체 범위를 나타낼 수 있는 정수 계열 형식이 없기 때문입니다.The reason is that no integral type exists that can represent the full range of ulong as well as the signed integral types.

위의 두 경우 모두 캐스트 식을 사용 하 여 피연산자 하나를 다른 피연산자와 호환 되는 형식으로 명시적으로 변환할 수 있습니다.In both of the above cases, a cast expression can be used to explicitly convert one operand to a type that is compatible with the other operand.

예제에서In the example

decimal AddPercent(decimal x, double percent) {
    return x * (1.0 + percent / 100.0);
}

decimal double로 곱할 수 없기 때문에 바인딩 시간 오류가 발생 합니다.a binding-time error occurs because a decimal cannot be multiplied by a double. 다음과 같이 두 번째 피연산자를 decimal으로 명시적으로 변환 하 여 오류를 해결 합니다.The error is resolved by explicitly converting the second operand to decimal, as follows:

decimal AddPercent(decimal x, double percent) {
    return x * (decimal)(1.0 + percent / 100.0);
}

리프트 연산자Lifted operators

리프트 연산자 를 사용 하면 null을 허용 하지 않는 값 형식에 대해 작동 하는 미리 정의 된 연산자와 사용자 정의 연산자가 해당 형식의 nullable 형식에도 사용 될 수 있습니다.Lifted operators permit predefined and user-defined operators that operate on non-nullable value types to also be used with nullable forms of those types. 리프트 연산자는 다음에 설명 된 대로 특정 요구 사항을 충족 하는 미리 정의 된 연산자 및 사용자 정의 연산자에서 생성 됩니다.Lifted operators are constructed from predefined and user-defined operators that meet certain requirements, as described in the following:

  • 단항 연산자의 경우For the unary operators

    +  ++  -  --  !  ~
    

    피연산자와 결과 형식이 null을 허용 하지 않는 값 형식인 경우 리프트 된 형태의 연산자가 존재 합니다.a lifted form of an operator exists if the operand and result types are both non-nullable value types. 리프트 된 형태는 단일 ? 한정자를 피연산자 및 결과 형식에 추가 하 여 생성 됩니다.The lifted form is constructed by adding a single ? modifier to the operand and result types. 리프트 연산자는 피연산자가 null 인 경우 null 값을 생성 합니다.The lifted operator produces a null value if the operand is null. 그렇지 않으면 리프트 연산자는 피연산자를의 래핑을 해제 하 고, 기본 연산자를 적용 하 고, 결과를 래핑합니다.Otherwise, the lifted operator unwraps the operand, applies the underlying operator, and wraps the result.

  • 이항 연산자의 경우For the binary operators

    +  -  *  /  %  &  |  ^  <<  >>
    

    피연산자와 결과 형식이 null을 허용 하지 않는 값 형식인 경우에는 리프트 된 형태의 연산자가 존재 합니다.a lifted form of an operator exists if the operand and result types are all non-nullable value types. 리프트 된 형태는 단일 ? 한정자를 각 피연산자와 결과 형식에 추가 하 여 생성 됩니다.The lifted form is constructed by adding a single ? modifier to each operand and result type. 두 피연산자 중 하나 또는 둘 다 null 인 경우 리프트 연산자는 null 값을 생성 합니다. 단, 부울 논리 연산자에 설명 된 대로 bool? 형식의 &| 연산자는 예외입니다.The lifted operator produces a null value if one or both operands are null (an exception being the & and | operators of the bool? type, as described in Boolean logical operators). 그렇지 않으면 리프트 연산자는 피연산자를의 래핑을 해제 하 고, 기본 연산자를 적용 하 고, 결과를 래핑합니다.Otherwise, the lifted operator unwraps the operands, applies the underlying operator, and wraps the result.

  • 같음 연산자의 경우For the equality operators

    ==  !=
    

    피연산자 형식이 null을 허용 하지 않는 값 형식이 고 결과 형식이 bool 이면 연산자의 리프트 된 형식이 존재 합니다.a lifted form of an operator exists if the operand types are both non-nullable value types and if the result type is bool. 리프트 된 형태는 단일 ? 한정자를 각 피연산자 형식에 추가 하 여 생성 됩니다.The lifted form is constructed by adding a single ? modifier to each operand type. 리프트 연산자는 두 null 값과 null이 아닌 값을 동일 하 게 간주 합니다.The lifted operator considers two null values equal, and a null value unequal to any non-null value. 두 피연산자가 모두 null이 아닌 경우 리프트 연산자는 피연산자를의 래핑을 해제 하 고 bool 결과를 생성 하는 기본 연산자를 적용 합니다.If both operands are non-null, the lifted operator unwraps the operands and applies the underlying operator to produce the bool result.

  • 관계형 연산자의 경우For the relational operators

    <  >  <=  >=
    

    피연산자 형식이 null을 허용 하지 않는 값 형식이 고 결과 형식이 bool 이면 연산자의 리프트 된 형식이 존재 합니다.a lifted form of an operator exists if the operand types are both non-nullable value types and if the result type is bool. 리프트 된 형태는 단일 ? 한정자를 각 피연산자 형식에 추가 하 여 생성 됩니다.The lifted form is constructed by adding a single ? modifier to each operand type. 리프트 연산자는 하나 또는 두 피연산자가 모두 null 인 경우 값 false을 생성 합니다.The lifted operator produces the value false if one or both operands are null. 그렇지 않으면 리프트 연산자는 피연산자를의 래핑을 해제 하 고 bool 결과를 생성 하는 기본 연산자를 적용 합니다.Otherwise, the lifted operator unwraps the operands and applies the underlying operator to produce the bool result.

멤버 조회Member lookup

멤버 조회는 형식의 컨텍스트에서 이름의 의미를 결정 하는 프로세스입니다.A member lookup is the process whereby the meaning of a name in the context of a type is determined. 멤버 조회는 식에서 simple_name (단순 이름) 또는 member_access (멤버 액세스)를 평가 하는 과정에서 발생할 수 있습니다.A member lookup can occur as part of evaluating a simple_name (Simple names) or a member_access (Member access) in an expression. Simple_name 또는 member_accessinvocation_expressionprimary_expression (메서드 호출)로 발생 하는 경우에는 멤버가 호출 되었다고 합니다.If the simple_name or member_access occurs as the primary_expression of an invocation_expression (Method invocations), the member is said to be invoked.

멤버가 메서드나 이벤트 이면이 고, 대리자 형식 (대리자) 또는 형식 @no__t (동적 형식)의 상수, 필드 또는 속성인 경우 멤버는 invocable이 됩니다.If a member is a method or event, or if it is a constant, field or property of either a delegate type (Delegates) or the type dynamic (The dynamic type), then the member is said to be invocable.

멤버 조회는 멤버의 이름 뿐만 아니라 멤버에 포함 된 형식 매개 변수 수 및 멤버에 액세스할 수 있는지 여부를 고려 합니다.Member lookup considers not only the name of a member but also the number of type parameters the member has and whether the member is accessible. 멤버 조회를 위해 제네릭 메서드와 중첩 된 제네릭 형식에는 해당 선언에 지정 된 형식 매개 변수 수가 있으며 다른 모든 멤버에는 0 형식 매개 변수가 있습니다.For the purposes of member lookup, generic methods and nested generic types have the number of type parameters indicated in their respective declarations and all other members have zero type parameters.

@ No__t-3 형식의 K @ no__t-2 형식 매개 변수를 사용 하는 name @ no__t-0의 멤버 조회는 다음과 같이 처리 됩니다.A member lookup of a name N with K type parameters in a type T is processed as follows:

  • 먼저 @ no__t-0 이라는 액세스 가능한 멤버 집합이 결정 됩니다.First, a set of accessible members named N is determined:
    • @No__t-0이 형식 매개 변수 이면 set은 @ no__t-3에 대 한 기본 제약 조건 또는 보조 제약 조건 (형식 매개 변수 제약 조건)으로 지정 된 각 형식에서 @ no__t-1 이라는 액세스 가능한 멤버 집합의 합집합입니다. object에서 이름이 @ no__t-4 인 액세스 가능한 멤버If T is a type parameter, then the set is the union of the sets of accessible members named N in each of the types specified as a primary constraint or secondary constraint (Type parameter constraints) for T, along with the set of accessible members named N in object.
    • 그렇지 않으면 집합은 상속 된 멤버와 object의 @ no__t-3 이라는 액세스 가능한 멤버를 포함 하 여 @ no__t-2에서 @ no__t-1 이라는 액세스 가능한 모든 (멤버 액세스) 멤버로 구성 됩니다.Otherwise, the set consists of all accessible (Member access) members named N in T, including inherited members and the accessible members named N in object. @No__t-0이 생성 된 형식인 경우 생성 된 형식의 멤버에 설명 된 대로 형식 인수를 대체 하 여 멤버 집합을 가져옵니다.If T is a constructed type, the set of members is obtained by substituting type arguments as described in Members of constructed types. @No__t-0 한정자를 포함 하는 멤버는 집합에서 제외 됩니다.Members that include an override modifier are excluded from the set.
  • 그런 다음 K이 0 이면 선언에 형식 매개 변수를 포함 하는 모든 중첩 형식이 제거 됩니다.Next, if K is zero, all nested types whose declarations include type parameters are removed. @No__t-0이 0이 아니면 형식 매개 변수 수가 다른 모든 멤버가 제거 됩니다.If K is not zero, all members with a different number of type parameters are removed. @No__t-0이 0 이면 형식 유추 프로세스 (형식 유추)에서 형식 인수를 유추할 수 있으므로 형식 매개 변수가 있는 메서드는 제거 되지 않습니다.Note that when K is zero, methods having type parameters are not removed, since the type inference process (Type inference) might be able to infer the type arguments.
  • 그런 다음 멤버가 호출되 면 모든 비invocable 멤버가 집합에서 제거 됩니다.Next, if the member is invoked, all non-invocable members are removed from the set.
  • 그런 다음 다른 멤버에 의해 숨겨진 멤버는 집합에서 제거 됩니다.Next, members that are hidden by other members are removed from the set. 집합에 있는 모든 멤버의 S.M은 (는) @ no__t가 선언 된 형식입니다. 여기서 S은 @-2 멤버가 선언 된 형식입니다.For every member S.M in the set, where S is the type in which the member M is declared, the following rules are applied:
    • @No__t-0이 상수, 필드, 속성, 이벤트 또는 열거형 멤버 이면 기본 형식 S에 선언 된 모든 멤버가 집합에서 제거 됩니다.If M is a constant, field, property, event, or enumeration member, then all members declared in a base type of S are removed from the set.
    • @No__t-0이 형식 선언 인 경우 S의 기본 형식에서 선언 된 형식이 아닌 모든 형식이 집합에서 제거 되며, S의 기본 형식에 선언 된 M와 동일한 수의 형식 매개 변수를 가진 모든 형식 선언이 집합에서 제거 됩니다.If M is a type declaration, then all non-types declared in a base type of S are removed from the set, and all type declarations with the same number of type parameters as M declared in a base type of S are removed from the set.
    • @No__t-0 인 경우 기본 형식 S에 선언 된 모든 비 메서드 멤버가 집합에서 제거 됩니다.If M is a method, then all non-method members declared in a base type of S are removed from the set.
  • 그런 다음 클래스 멤버로 숨겨진 인터페이스 멤버가 집합에서 제거 됩니다.Next, interface members that are hidden by class members are removed from the set. 이 단계는 T이 형식 매개 변수이 고 Tobject 및 비어 있지 않은 유효 인터페이스 집합 (형식 매개 변수 제약 조건) 이외의 유효한 기본 클래스가 있는 경우에만 적용 됩니다.This step only has an effect if T is a type parameter and T has both an effective base class other than object and a non-empty effective interface set (Type parameter constraints). @No__t 집합에 있는 모든 멤버의 S.M은 (는) 멤버 M가 선언 된 형식입니다. Sobject 이외의 클래스 선언 인 경우에는 다음 규칙이 적용 됩니다.For every member S.M in the set, where S is the type in which the member M is declared, the following rules are applied if S is a class declaration other than object:
    • @No__t-0이 상수, 필드, 속성, 이벤트, 열거형 멤버 또는 형식 선언 인 경우 인터페이스 선언에 선언 된 모든 멤버가 집합에서 제거 됩니다.If M is a constant, field, property, event, enumeration member, or type declaration, then all members declared in an interface declaration are removed from the set.
    • @No__t-0 인 경우 인터페이스 선언에 선언 된 모든 비 메서드 멤버가 집합에서 제거 되 고 인터페이스 선언에서 선언 된 M과 동일한 시그니처를 가진 모든 메서드가 집합에서 제거 됩니다.If M is a method, then all non-method members declared in an interface declaration are removed from the set, and all methods with the same signature as M declared in an interface declaration are removed from the set.
  • 마지막으로 숨겨진 멤버가 제거 되 면 조회 결과가 다음과 같이 결정 됩니다.Finally, having removed hidden members, the result of the lookup is determined:
    • 집합이 메서드가 아닌 단일 멤버로 구성 된 경우이 멤버가 조회 결과입니다.If the set consists of a single member that is not a method, then this member is the result of the lookup.
    • 그렇지 않고 집합에 메서드만 포함 된 경우이 메서드 그룹이 조회 결과입니다.Otherwise, if the set contains only methods, then this group of methods is the result of the lookup.
    • 그렇지 않으면 조회가 모호 하 고 바인딩 시간 오류가 발생 합니다.Otherwise, the lookup is ambiguous, and a binding-time error occurs.

형식 매개 변수 및 인터페이스 이외의 형식에서 멤버를 조회 하 고 엄격 하 게 단일 상속을 하는 인터페이스의 멤버 조회 (상속 체인의 각 인터페이스에 정확히 0 개 또는 하나의 직접 기본 인터페이스가 있음)의 경우 조회 규칙의 효과는 파생 멤버는 이름이 나 시그니처가 같은 기본 멤버를 숨깁니다.For member lookups in types other than type parameters and interfaces, and member lookups in interfaces that are strictly single-inheritance (each interface in the inheritance chain has exactly zero or one direct base interface), the effect of the lookup rules is simply that derived members hide base members with the same name or signature. 이러한 단일 상속 조회는 모호 하지 않습니다.Such single-inheritance lookups are never ambiguous. 여러 상속 인터페이스의 멤버 조회에서 발생할 수 있는 모호성은 인터페이스 멤버 액세스에 설명 되어 있습니다.The ambiguities that can possibly arise from member lookups in multiple-inheritance interfaces are described in Interface member access.

기본 형식Base types

멤버 조회를 위해 형식 T은 다음 기본 형식으로 간주 됩니다.For purposes of member lookup, a type T is considered to have the following base types:

  • @No__t-0 object 이면 T에 기본 형식이 없습니다.If T is object, then T has no base type.
  • @No__t-0이 enum_type인 경우 @no__t의 기본 형식은-3, System.ValueTypeobject @no__t 클래스 형식입니다.If T is an enum_type, the base types of T are the class types System.Enum, System.ValueType, and object.
  • @No__t-0이 struct_type인 경우 @no__t의 기본 형식은-3 @no__t 클래스 형식이 고 object입니다.If T is a struct_type, the base types of T are the class types System.ValueType and object.
  • @No__t-0이 class_type인 경우 @no__t의 기본 형식은-4의 기본 @no__t 클래스입니다.-2는 클래스 형식 object를 포함 합니다.If T is a class_type, the base types of T are the base classes of T, including the class type object.
  • @No__t-0이 interface_type인 경우 @no__t의 기본 형식은-3 @no__t 기본 인터페이스이 고 클래스 형식은-4 @no__t.If T is an interface_type, the base types of T are the base interfaces of T and the class type object.
  • @No__t-0이 array_type인 경우 @no__t의 기본 형식은-3 @no__t 클래스 형식이 고 object입니다.If T is an array_type, the base types of T are the class types System.Array and object.
  • @No__t-0이 delegate_type인 경우 @no__t의 기본 형식은-3 @no__t 클래스 형식이 고 object입니다.If T is a delegate_type, the base types of T are the class types System.Delegate and object.

함수 멤버Function members

함수 멤버는 실행 가능한 문을 포함 하는 멤버입니다.Function members are members that contain executable statements. 함수 멤버는 항상 형식의 멤버 이며 네임 스페이스의 멤버일 수 없습니다.Function members are always members of types and cannot be members of namespaces. C#는 다음과 같은 함수 멤버 범주를 정의 합니다.C# defines the following categories of function members:

  • 메서드Methods
  • 속성Properties
  • 이벤트Events
  • 인덱서Indexers
  • 사용자 정의 연산자User-defined operators
  • 인스턴스 생성자Instance constructors
  • 정적 생성자Static constructors
  • 소멸자Destructors

소멸자 및 정적 생성자를 제외 하 고 (명시적으로 호출할 수 없음) 함수 멤버에 포함 된 문은 함수 멤버 호출을 통해 실행 됩니다.Except for destructors and static constructors (which cannot be invoked explicitly), the statements contained in function members are executed through function member invocations. 함수 멤버 호출을 작성 하는 실제 구문은 특정 함수 멤버 범주에 따라 달라 집니다.The actual syntax for writing a function member invocation depends on the particular function member category.

함수 멤버 호출의 인수 목록 (인수목록)은 함수 멤버의 매개 변수에 대 한 실제 값 또는 변수 참조를 제공 합니다.The argument list (Argument lists) of a function member invocation provides actual values or variable references for the parameters of the function member.

제네릭 메서드를 호출할 때 형식 유추를 사용 하 여 메서드에 전달할 형식 인수 집합을 확인할 수 있습니다.Invocations of generic methods may employ type inference to determine the set of type arguments to pass to the method. 이 프로세스는 형식 유추에 설명 되어 있습니다.This process is described in Type inference.

메서드, 인덱서, 연산자 및 인스턴스 생성자의 호출은 오버 로드 확인을 사용 하 여 호출할 함수 멤버의 후보 집합을 결정 합니다.Invocations of methods, indexers, operators and instance constructors employ overload resolution to determine which of a candidate set of function members to invoke. 이 프로세스는 오버 로드 확인에 설명 되어 있습니다.This process is described in Overload resolution.

오버 로드 확인을 통해 특정 함수 멤버를 바인딩 시간에 식별 한 후에는 함수 멤버를 호출 하는 실제 런타임 프로세스가 동적 오버 로드 확인의 컴파일 타임 검사에 설명 되어 있습니다.Once a particular function member has been identified at binding-time, possibly through overload resolution, the actual run-time process of invoking the function member is described in Compile-time checking of dynamic overload resolution.

다음 표에서는 명시적으로 호출할 수 있는 함수 멤버의 여섯 가지 범주와 관련 된 구문에서 발생 하는 처리를 요약 합니다.The following table summarizes the processing that takes place in constructs involving the six categories of function members that can be explicitly invoked. 테이블에서 e, x, @no__t 2, value은 변수 또는 값으로 분류 된 식을 나타내고, @no__t은 형식으로 분류 된 식을 나타내고, F는 메서드의 단순한 이름이 고, P은 속성의 단순한 이름입니다.In the table, e, x, y, and value indicate expressions classified as variables or values, T indicates an expression classified as a type, F is the simple name of a method, and P is the simple name of a property.

구축Construct 예제Example 설명Description
메서드 호출Method invocation F(x,y) 포함 하는 클래스 또는 구조체에서 가장 F을 선택 하는 오버 로드 확인이 적용 됩니다.Overload resolution is applied to select the best method F in the containing class or struct. 인수 목록 (x,y)을 사용 하 여 메서드를 호출 합니다.The method is invoked with the argument list (x,y). 메서드가 @no__t 되지 않은 경우 인스턴스 식 this입니다.If the method is not static, the instance expression is this.
T.F(x,y) 오버 로드 확인이 적용 되어 클래스 또는 구조체 T에서 F의 가장 적합 한 메서드를 선택 합니다.Overload resolution is applied to select the best method F in the class or struct T. 메서드가 0 @no__t 되지 않으면 바인딩 시간 오류가 발생 합니다.A binding-time error occurs if the method is not static. 인수 목록 (x,y)을 사용 하 여 메서드를 호출 합니다.The method is invoked with the argument list (x,y).
e.F(x,y) @No__t 형식에서 제공 하는 클래스, 구조체 또는 인터페이스에서 최적의 메서드 F를 선택 하기 위해 오버 로드 확인이 적용 됩니다.Overload resolution is applied to select the best method F in the class, struct, or interface given by the type of e. 메서드가-0 @no__t 경우 바인딩 시간 오류가 발생 합니다.A binding-time error occurs if the method is static. 이 메서드는 인스턴스 식 e을 사용 하 여 호출 되며 인수 목록에는-1이 @no__t.The method is invoked with the instance expression e and the argument list (x,y).
속성 액세스Property access P 포함 하는 클래스 또는 구조체에서 속성 Pget 접근자가 호출 됩니다.The get accessor of the property P in the containing class or struct is invoked. @No__t-0이 쓰기 전용 이면 컴파일 시간 오류가 발생 합니다.A compile-time error occurs if P is write-only. @No__t-0이-1 @no__t 되지 않은 경우 인스턴스 식은-2 @no__t 됩니다.If P is not static, the instance expression is this.
P = value 포함 하는 클래스 또는 구조체에 있는 @no__t 속성의 set 접근자는 인수 목록 (value)를 사용 하 여 호출 됩니다.The set accessor of the property P in the containing class or struct is invoked with the argument list (value). @No__t-0이 읽기 전용인 경우 컴파일 시간 오류가 발생 합니다.A compile-time error occurs if P is read-only. @No__t-0이-1 @no__t 되지 않은 경우 인스턴스 식은-2 @no__t 됩니다.If P is not static, the instance expression is this.
T.P 클래스 또는 구조체 T에서 @no__t 속성의 get 접근자가 호출 됩니다.The get accessor of the property P in the class or struct T is invoked. @No__t-0이-1 @no__t 되지 않거나 P가 쓰기 전용 이면 컴파일 시간 오류가 발생 합니다.A compile-time error occurs if P is not static or if P is write-only.
T.P = value 클래스 또는 구조체 T에 있는 @no__t 속성의 set 접근자는 인수 목록 (value)으로 호출 됩니다.The set accessor of the property P in the class or struct T is invoked with the argument list (value). @No__t-0이-1 @no__t 아니거나 P가 읽기 전용인 경우 컴파일 시간 오류가 발생 합니다.A compile-time error occurs if P is not static or if P is read-only.
e.P @No__t-2 형식에서 제공 하는 클래스, 구조체 또는 인터페이스에 있는 @no__t 속성의 get 접근자는 인스턴스 식 e을 사용 하 여 호출 됩니다.The get accessor of the property P in the class, struct, or interface given by the type of e is invoked with the instance expression e. @No__t-0이-1 @no__t 이거나 P가 쓰기 전용 이면 바인딩 시간 오류가 발생 합니다.A binding-time error occurs if P is static or if P is write-only.
e.P = value @No__t-2 형식에서 제공 하는 클래스, 구조체 또는 인터페이스에 있는 클래스, 구조체 또는 인터페이스에 있는 @no__t 속성의 set 접근자는 인스턴스 식 e 및 인수 목록 (value)를 사용 하 여 호출 됩니다.The set accessor of the property P in the class, struct, or interface given by the type of e is invoked with the instance expression e and the argument list (value). @No__t-0이-1 @no__t 이거나 P가 읽기 전용인 경우 바인딩 시간 오류가 발생 합니다.A binding-time error occurs if P is static or if P is read-only.
이벤트 액세스Event access E += value 포함 하는 클래스 또는 구조체에서 이벤트 Eadd 접근자가 호출 됩니다.The add accessor of the event E in the containing class or struct is invoked. @No__t-0이 static이 아니면 인스턴스 식 this입니다.If E is not static, the instance expression is this.
E -= value 포함 하는 클래스 또는 구조체에서 이벤트 Eremove 접근자가 호출 됩니다.The remove accessor of the event E in the containing class or struct is invoked. @No__t-0이 static이 아니면 인스턴스 식 this입니다.If E is not static, the instance expression is this.
T.E += value 클래스의 이벤트 Eadd 접근자 T가 호출 됩니다.The add accessor of the event E in the class or struct T is invoked. @No__t-0이 static이 아니면 바인딩 시간 오류가 발생 합니다.A binding-time error occurs if E is not static.
T.E -= value 클래스의 이벤트 Eremove 접근자 T가 호출 됩니다.The remove accessor of the event E in the class or struct T is invoked. @No__t-0이 static이 아니면 바인딩 시간 오류가 발생 합니다.A binding-time error occurs if E is not static.
e.E += value @No__t-2 형식에서 제공 하는 클래스, 구조체 또는 인터페이스에서 @no__t 이벤트의 add 접근자는 인스턴스 식 e을 사용 하 여 호출 됩니다.The add accessor of the event E in the class, struct, or interface given by the type of e is invoked with the instance expression e. @No__t-0이 정적 이면 바인딩 시간 오류가 발생 합니다.A binding-time error occurs if E is static.
e.E -= value @No__t-2 형식에서 제공 하는 클래스, 구조체 또는 인터페이스에서 @no__t 이벤트의 remove 접근자는 인스턴스 식 e을 사용 하 여 호출 됩니다.The remove accessor of the event E in the class, struct, or interface given by the type of e is invoked with the instance expression e. @No__t-0이 정적 이면 바인딩 시간 오류가 발생 합니다.A binding-time error occurs if E is static.
인덱서 액세스Indexer access e[x,y] E 형식에서 제공 하는 클래스, 구조체 또는 인터페이스에서 가장 적합 한 인덱서를 선택 하기 위해 오버 로드 확인이 적용 됩니다.Overload resolution is applied to select the best indexer in the class, struct, or interface given by the type of e. 인덱서의 get 접근자는 인스턴스 식 e을 사용 하 여 호출 되 고 인수 목록에는-2 @no__t 됩니다.The get accessor of the indexer is invoked with the instance expression e and the argument list (x,y). 인덱서가 쓰기 전용 이면 바인딩 시간 오류가 발생 합니다.A binding-time error occurs if the indexer is write-only.
e[x,y] = value @No__t 형식에서 제공 하는 클래스, 구조체 또는 인터페이스에서 가장 적합 한 인덱서를 선택 하기 위해 오버 로드 확인이 적용 됩니다.Overload resolution is applied to select the best indexer in the class, struct, or interface given by the type of e. 인덱서의 set 접근자는 인스턴스 식 e을 사용 하 여 호출 되 고 인수 목록에는-2 @no__t 됩니다.The set accessor of the indexer is invoked with the instance expression e and the argument list (x,y,value). 인덱서가 읽기 전용 이면 바인딩 시간 오류가 발생 합니다.A binding-time error occurs if the indexer is read-only.
연산자 호출Operator invocation -x @No__t 형식에서 제공 하는 클래스 또는 구조체에서 가장 적합 한 단항 연산자를 선택 하는 오버 로드 확인이 적용 됩니다.Overload resolution is applied to select the best unary operator in the class or struct given by the type of x. 선택한 연산자는 인수 목록을 사용 하 여 (x)으로 호출 됩니다.The selected operator is invoked with the argument list (x).
x + y @No__t-0 및 y 형식으로 지정 된 클래스 또는 구조체에서 가장 적합 한 이항 연산자를 선택 하기 위해 오버 로드 확인이 적용 됩니다.Overload resolution is applied to select the best binary operator in the classes or structs given by the types of x and y. 선택한 연산자는 인수 목록을 사용 하 여 (x,y)으로 호출 됩니다.The selected operator is invoked with the argument list (x,y).
인스턴스 생성자 호출Instance constructor invocation new T(x,y) 클래스 또는 구조체 T에서 최상의 인스턴스 생성자를 선택 하기 위해 오버 로드 확인이 적용 됩니다.Overload resolution is applied to select the best instance constructor in the class or struct T. 인스턴스 생성자는 인수 목록을 사용 하 여 (x,y)으로 호출 됩니다.The instance constructor is invoked with the argument list (x,y).

인수 목록Argument lists

모든 함수 멤버 및 대리자 호출에는 함수 멤버의 매개 변수에 대 한 실제 값 또는 변수 참조를 제공 하는 인수 목록이 포함 되어 있습니다.Every function member and delegate invocation includes an argument list which provides actual values or variable references for the parameters of the function member. 함수 멤버 호출의 인수 목록을 지정 하는 구문은 함수 멤버 범주에 따라 달라 집니다.The syntax for specifying the argument list of a function member invocation depends on the function member category:

  • 인스턴스 생성자, 메서드, 인덱서 및 대리자의 경우 인수는 아래에 설명 된 대로 argument_list로 지정 됩니다.For instance constructors, methods, indexers and delegates, the arguments are specified as an argument_list, as described below. 인덱서의 경우 set 접근자를 호출 하는 경우 인수 목록에는 할당 연산자의 오른쪽 피연산자로 지정 된 식도 추가로 포함 됩니다.For indexers, when invoking the set accessor, the argument list additionally includes the expression specified as the right operand of the assignment operator.
  • 속성의 경우 get 접근자를 호출할 때 인수 목록이 비어 있고 set 접근자를 호출할 때 할당 연산자의 오른쪽 피연산자로 지정 된 식으로 구성 됩니다.For properties, the argument list is empty when invoking the get accessor, and consists of the expression specified as the right operand of the assignment operator when invoking the set accessor.
  • 이벤트의 경우 인수 목록은 += 또는 -= 연산자의 오른쪽 피연산자로 지정 된 식으로 구성 됩니다.For events, the argument list consists of the expression specified as the right operand of the += or -= operator.
  • 사용자 정의 연산자의 경우 인수 목록은 단항 연산자의 단일 피연산자 또는 이항 연산자의 두 피연산자로 구성 됩니다.For user-defined operators, the argument list consists of the single operand of the unary operator or the two operands of the binary operator.

속성 (속성), 이벤트 (이벤트) 및 사용자 정의 연산자 (연산자)의 인수는 항상 값 매개 변수 (값 매개 변수)로 전달 됩니다.The arguments of properties (Properties), events (Events), and user-defined operators (Operators) are always passed as value parameters (Value parameters). 인덱서 (인덱서)의 인수는 항상 값 매개 변수 (값 매개 변수) 또는 매개 변수 배열 (매개 변수 배열)로 전달 됩니다.The arguments of indexers (Indexers) are always passed as value parameters (Value parameters) or parameter arrays (Parameter arrays). 이러한 함수 멤버 범주에 대 한 참조 및 출력 매개 변수는 지원 되지 않습니다.Reference and output parameters are not supported for these categories of function members.

인스턴스 생성자, 메서드, 인덱서 또는 대리자 호출의 인수는 argument_list로 지정 됩니다.The arguments of an instance constructor, method, indexer or delegate invocation are specified as an argument_list:

argument_list
    : argument (',' argument)*
    ;

argument
    : argument_name? argument_value
    ;

argument_name
    : identifier ':'
    ;

argument_value
    : expression
    | 'ref' variable_reference
    | 'out' variable_reference
    ;

Argument_list 는 하나 이상의 인수로구성 되며 쉼표로 구분 됩니다.An argument_list consists of one or more arguments, separated by commas. 각 인수는 선택적 argument_name 다음에 argument_value로 구성 됩니다.Each argument consists of an optional argument_name followed by an argument_value. Argument_name 를 사용 하는 인수명명 된 인수라고 하는 반면, argument_name 없는 인수위치 인수입니다.An argument with an argument_name is referred to as a named argument, whereas an argument without an argument_name is a positional argument. 위치 인수가 argument_list의 명명 된 인수 뒤에 표시 되는 것은 오류입니다.It is an error for a positional argument to appear after a named argument in an argument_list.

Argument_value 는 다음 형식 중 하나를 사용할 수 있습니다.The argument_value can take one of the following forms:

  • 인수가 값 매개 변수 (값 매개 변수)로 전달 되는지 여부를 나타내는 입니다.An expression, indicating that the argument is passed as a value parameter (Value parameters).
  • 키워드는-0 다음에 variable_reference (변수 참조)를 @no__t 하 여 인수가 참조 매개 변수 (참조 매개 변수)로 전달 됨을 나타냅니다.The keyword ref followed by a variable_reference (Variable references), indicating that the argument is passed as a reference parameter (Reference parameters). 변수는 참조 매개 변수로 전달 되기 전에 명확 하 게 할당 되어야 합니다 (한정).A variable must be definitely assigned (Definite assignment) before it can be passed as a reference parameter. 키워드는-0 다음에 variable_reference (변수 참조)를 @no__t 하 여 인수가 출력 매개 변수 (출력 매개 변수)로 전달 됨을 나타냅니다.The keyword out followed by a variable_reference (Variable references), indicating that the argument is passed as an output parameter (Output parameters). 변수는 변수가 출력 매개 변수로 전달 되는 함수 멤버 호출을 따라 명확 하게 할당 된것으로 간주 됩니다.A variable is considered definitely assigned (Definite assignment) following a function member invocation in which the variable is passed as an output parameter.

해당 매개 변수Corresponding parameters

인수 목록의 각 인수에 대해 호출 되는 함수 멤버 또는 대리자에 해당 하는 매개 변수가 있어야 합니다.For each argument in an argument list there has to be a corresponding parameter in the function member or delegate being invoked.

다음에 사용 되는 매개 변수 목록은 다음과 같이 결정 됩니다.The parameter list used in the following is determined as follows:

  • 클래스에 정의 된 가상 메서드 및 인덱서의 경우 매개 변수 목록은 수신기의 정적 형식으로 시작 하 고 기본 클래스를 통해 검색 하는 함수 멤버의 가장 구체적인 선언 또는 재정의에서 선택 됩니다.For virtual methods and indexers defined in classes, the parameter list is picked from the most specific declaration or override of the function member, starting with the static type of the receiver, and searching through its base classes.
  • 인터페이스 메서드 및 인덱서의 경우 인터페이스 형식에서 시작 하 여 기본 인터페이스를 검색 하는 가장 구체적인 멤버 정의를 매개 변수 목록에서 선택 합니다.For interface methods and indexers, the parameter list is picked form the most specific definition of the member, starting with the interface type and searching through the base interfaces. 고유한 매개 변수 목록을 찾을 수 없는 경우, 호출에서 명명 된 매개 변수를 사용 하거나 선택적 인수를 생략할 수 없도록 액세스할 수 없는 이름 및 선택적 매개 변수가 생성 된 매개 변수 목록이 생성 됩니다.If no unique parameter list is found, a parameter list with inaccessible names and no optional parameters is constructed, so that invocations cannot use named parameters or omit optional arguments.
  • 부분 메서드 (partial method)의 경우 정의 하는 부분 메서드 (partial method) 선언의 매개 변수 목록이 사용 됩니다.For partial methods, the parameter list of the defining partial method declaration is used.
  • 다른 모든 함수 멤버 및 대리자의 경우 사용 되는 매개 변수 목록이 하나 뿐입니다.For all other function members and delegates there is only a single parameter list, which is the one used.

인수 또는 매개 변수의 위치는 인수 목록 또는 매개 변수 목록에서 앞에 나오는 인수 또는 매개 변수의 수로 정의 됩니다.The position of an argument or parameter is defined as the number of arguments or parameters preceding it in the argument list or parameter list.

함수 멤버 인수에 해당 하는 매개 변수는 다음과 같이 설정 됩니다.The corresponding parameters for function member arguments are established as follows:

  • 인스턴스 생성자, 메서드, 인덱서 및 대리자의 argument_list 의 인수:Arguments in the argument_list of instance constructors, methods, indexers and delegates:
    • Fixed 매개 변수가 매개 변수 목록의 같은 위치에서 발생 하는 위치 인수는 해당 매개 변수에 해당 합니다.A positional argument where a fixed parameter occurs at the same position in the parameter list corresponds to that parameter.
    • 일반 형식으로 호출 되는 매개 변수 배열을 사용 하는 함수 멤버의 위치 인수는 매개 변수 목록에서 같은 위치에 있어야 하는 매개 변수 배열에 해당 합니다.A positional argument of a function member with a parameter array invoked in its normal form corresponds to the parameter array, which must occur at the same position in the parameter list.
    • 확장 된 형식으로 호출 되는 매개 변수 배열을 사용 하는 함수 멤버의 위치 인수 (매개 변수 목록의 같은 위치에서 고정 매개 변수가 발생 하지 않음)는 매개 변수 배열의 요소에 해당 합니다.A positional argument of a function member with a parameter array invoked in its expanded form, where no fixed parameter occurs at the same position in the parameter list, corresponds to an element in the parameter array.
    • 명명 된 인수는 매개 변수 목록에 있는 동일한 이름의 매개 변수에 해당 합니다.A named argument corresponds to the parameter of the same name in the parameter list.
    • 인덱서의 경우 set 접근자를 호출할 때 할당 연산자의 오른쪽 피연산자로 지정 된 식은 set 접근자 선언의 암시적 value 매개 변수에 해당 합니다.For indexers, when invoking the set accessor, the expression specified as the right operand of the assignment operator corresponds to the implicit value parameter of the set accessor declaration.
  • 속성의 경우 get 접근자를 호출할 때 인수가 없습니다.For properties, when invoking the get accessor there are no arguments. @No__t-0 접근자를 호출 하는 경우 할당 연산자의 오른쪽 피연산자로 지정 된 식은 set 접근자 선언의 암시적 value 매개 변수에 해당 합니다.When invoking the set accessor, the expression specified as the right operand of the assignment operator corresponds to the implicit value parameter of the set accessor declaration.
  • 사용자 정의 단항 연산자 (변환 포함)의 경우 단일 피연산자는 연산자 선언의 단일 매개 변수에 해당 합니다.For user-defined unary operators (including conversions), the single operand corresponds to the single parameter of the operator declaration.
  • 사용자 정의 이항 연산자의 경우 왼쪽 피연산자는 첫 번째 매개 변수에 해당 하 고 오른쪽 피연산자는 연산자 선언의 두 번째 매개 변수에 해당 합니다.For user-defined binary operators, the left operand corresponds to the first parameter, and the right operand corresponds to the second parameter of the operator declaration.

인수 목록의 런타임 계산Run-time evaluation of argument lists

함수 멤버 호출 (동적 오버 로드 확인의 컴파일 시간 검사)을 런타임 처리 하는 동안 다음과 같이 인수 목록의 식 또는 변수 참조를 왼쪽에서 오른쪽으로 계산 합니다.During the run-time processing of a function member invocation (Compile-time checking of dynamic overload resolution), the expressions or variable references of an argument list are evaluated in order, from left to right, as follows:

  • 값 매개 변수의 경우 인수 식이 계산 되 고 해당 매개 변수 형식에 대 한 암시적 변환 (암시적 변환)이 수행 됩니다.For a value parameter, the argument expression is evaluated and an implicit conversion (Implicit conversions) to the corresponding parameter type is performed. 결과 값은 함수 멤버 호출에서 value 매개 변수의 초기 값이 됩니다.The resulting value becomes the initial value of the value parameter in the function member invocation.
  • 참조 또는 출력 매개 변수의 경우 변수 참조가 평가 되 고 결과 저장소 위치가 함수 멤버 호출에서 매개 변수가 나타내는 저장소 위치가 됩니다.For a reference or output parameter, the variable reference is evaluated and the resulting storage location becomes the storage location represented by the parameter in the function member invocation. 참조 또는 출력 매개 변수로 지정 된 변수 참조가 reference_type의 배열 요소인 경우 배열의 요소 형식이 매개 변수의 형식과 동일한 지 확인 하기 위해 런타임 검사가 수행 됩니다.If the variable reference given as a reference or output parameter is an array element of a reference_type, a run-time check is performed to ensure that the element type of the array is identical to the type of the parameter. 이 검사가 실패 하면 System.ArrayTypeMismatchException이 throw 됩니다.If this check fails, a System.ArrayTypeMismatchException is thrown.

메서드, 인덱서 및 인스턴스 생성자는 가장 오른쪽에 있는 매개 변수를 매개 변수 배열 (매개 변수배열)로 선언할 수 있습니다.Methods, indexers, and instance constructors may declare their right-most parameter to be a parameter array (Parameter arrays). 이러한 함수 멤버는 적용 되는 (적용 가능한 함수 멤버)에 따라 일반 폼 이나 확장 된 형식으로 호출 됩니다.Such function members are invoked either in their normal form or in their expanded form depending on which is applicable (Applicable function member):

  • 매개 변수 배열을 사용 하는 함수 멤버를 일반 형식으로 호출 하는 경우 매개 변수 배열에 지정 된 인수는 매개 변수 배열 형식에 대해 암시적으로 변환 가능 하 고 암시적으로변환되는 단일 식 이어야 합니다.When a function member with a parameter array is invoked in its normal form, the argument given for the parameter array must be a single expression that is implicitly convertible (Implicit conversions) to the parameter array type. 이 경우 매개 변수 배열은 값 매개 변수 처럼 정확 하 게 작동 합니다.In this case, the parameter array acts precisely like a value parameter.
  • 매개 변수 배열을 사용하는 함수 멤버가 확장된 형식으로 호출되면 호출에서 매개 변수 배열에 대해 0개 이상의 위치 인수를 지정해야 합니다. 여기서 각 인수는 암시적으로 변환 가능한 식(암시적 변환)입니다.When a function member with a parameter array is invoked in its expanded form, the invocation must specify zero or more positional arguments for the parameter array, where each argument is an expression that is implicitly convertible (Implicit conversions) to the element type of the parameter array. 이 경우 호출에서 인수 수에 해당 하는 길이를 사용 하 여 매개 변수 배열 형식의 인스턴스를 만들고, 지정 된 인수 값을 사용 하 여 배열 인스턴스의 요소를 초기화 하 고, 새로 만든 배열 인스턴스를 실제 값으로 사용 합니다. t.In this case, the invocation creates an instance of the parameter array type with a length corresponding to the number of arguments, initializes the elements of the array instance with the given argument values, and uses the newly created array instance as the actual argument.

인수 목록의 식은 항상 작성 된 순서 대로 평가 됩니다.The expressions of an argument list are always evaluated in the order they are written. 따라서 예제는Thus, the example

class Test
{
    static void F(int x, int y = -1, int z = -2) {
        System.Console.WriteLine("x = {0}, y = {1}, z = {2}", x, y, z);
    }

    static void Main() {
        int i = 0;
        F(i++, i++, i++);
        F(z: i++, x: i++);
    }
}

는 출력을 생성합니다.produces the output

x = 0, y = 1, z = 2
x = 4, y = -1, z = 3

배열 분산 규칙 (배열 공분산)은 B에서 A로의 암시적 참조 변환이 있는 경우-1의 배열 형식에 @no__t 대 한 참조가 A[] 인 배열 형식의 값을 허용 합니다.The array co-variance rules (Array covariance) permit a value of an array type A[] to be a reference to an instance of an array type B[], provided an implicit reference conversion exists from B to A. 이러한 규칙으로 인해 reference_type 의 배열 요소가 참조 또는 출력 매개 변수로 전달 될 때 배열의 실제 요소 형식이 매개 변수의 실제 요소 형식과 동일한 지 확인 하는 데 런타임 검사가 필요 합니다.Because of these rules, when an array element of a reference_type is passed as a reference or output parameter, a run-time check is required to ensure that the actual element type of the array is identical to that of the parameter. 예제에서In the example

class Test
{
    static void F(ref object x) {...}

    static void Main() {
        object[] a = new object[10];
        object[] b = new string[10];
        F(ref a[0]);        // Ok
        F(ref b[1]);        // ArrayTypeMismatchException
    }
}

F에 대 한 두 번째 호출로 인해 b의 실제 요소 형식이 object가 아닌 string 이기 때문에 System.ArrayTypeMismatchException이 throw 됩니다.the second invocation of F causes a System.ArrayTypeMismatchException to be thrown because the actual element type of b is string and not object.

매개 변수 배열을 사용 하는 함수 멤버가 확장 된 형식으로 호출 될 때 확장 된 매개 변수 주위에 배열 이니셜라이저 (배열 생성 식)를 사용 하는 배열 생성 식이 삽입 된 것 처럼 호출이 처리 됩니다.When a function member with a parameter array is invoked in its expanded form, the invocation is processed exactly as if an array creation expression with an array initializer (Array creation expressions) was inserted around the expanded parameters. 예를 들어 선언이 지정 된 경우For example, given the declaration

void F(int x, int y, params object[] args);

메서드의 확장 된 형태에 대 한 다음 호출the following invocations of the expanded form of the method

F(10, 20);
F(10, 20, 30, 40);
F(10, 20, 1, "hello", 3.0);

정확히 일치correspond exactly to

F(10, 20, new object[] {});
F(10, 20, new object[] {30, 40});
F(10, 20, new object[] {1, "hello", 3.0});

특히 매개 변수 배열에 대해 0 개의 인수가 지정 된 경우 빈 배열이 생성 됩니다.In particular, note that an empty array is created when there are zero arguments given for the parameter array.

해당 하는 선택적 매개 변수를 사용 하 여 함수 멤버에서 인수를 생략 하면 함수 멤버 선언의 기본 인수가 암시적으로 전달 됩니다.When arguments are omitted from a function member with corresponding optional parameters, the default arguments of the function member declaration are implicitly passed. 이러한 함수는 항상 일정 하기 때문에 나머지 인수의 계산 순서에는 영향을 주지 않습니다.Because these are always constant, their evaluation will not impact the evaluation order of the remaining arguments.

형식 유추Type inference

형식 인수를 지정 하지 않고 제네릭 메서드를 호출 하는 경우 형식 유추 프로세스는 호출에 대 한 형식 인수를 유추 하려고 합니다.When a generic method is called without specifying type arguments, a type inference process attempts to infer type arguments for the call. 형식 유추가 있으면 제네릭 메서드를 호출 하는 데 더 편리한 구문을 사용할 수 있으며, 프로그래머가 중복 형식 정보를 지정 하지 않아도 됩니다.The presence of type inference allows a more convenient syntax to be used for calling a generic method, and allows the programmer to avoid specifying redundant type information. 예를 들어, 메서드 선언이 있다고 가정 합니다.For example, given the method declaration:

class Chooser
{
    static Random rand = new Random();

    public static T Choose<T>(T first, T second) {
        return (rand.Next(2) == 0)? first: second;
    }
}

형식 인수를 명시적으로 지정 하지 않고 Choose 메서드를 호출할 수 있습니다.it is possible to invoke the Choose method without explicitly specifying a type argument:

int i = Chooser.Choose(5, 213);                 // Calls Choose<int>

string s = Chooser.Choose("foo", "bar");        // Calls Choose<string>

형식 유추를 통해 형식 인수 intstring은 메서드에 대 한 인수에서 결정 됩니다.Through type inference, the type arguments int and string are determined from the arguments to the method.

형식 유추는 메서드 호출 (메서드 호출)에 대 한 바인딩 시간 처리의 일부로 발생 하며 호출의 오버 로드 확인 단계 전에 발생 합니다.Type inference occurs as part of the binding-time processing of a method invocation (Method invocations) and takes place before the overload resolution step of the invocation. 메서드 호출에서 특정 메서드 그룹을 지정 하 고 메서드 호출의 일부로 형식 인수를 지정 하지 않은 경우 형식 유추가 메서드 그룹의 각 제네릭 메서드에 적용 됩니다.When a particular method group is specified in a method invocation, and no type arguments are specified as part of the method invocation, type inference is applied to each generic method in the method group. 형식 유추가 성공 하면 유추 된 형식 인수를 사용 하 여 후속 오버 로드 확인에 대 한 인수의 형식을 결정 합니다.If type inference succeeds, then the inferred type arguments are used to determine the types of arguments for subsequent overload resolution. 오버 로드 확인에서 제네릭 메서드를 호출 하는 것으로 선택 하는 경우 유추 된 형식 인수는 호출에 대 한 실제 형식 인수로 사용 됩니다.If overload resolution chooses a generic method as the one to invoke, then the inferred type arguments are used as the actual type arguments for the invocation. 특정 메서드에 대 한 형식 유추가 실패할 경우 해당 메서드는 오버 로드 확인에 참여 하지 않습니다.If type inference for a particular method fails, that method does not participate in overload resolution. 자체에서 형식 유추의 실패로 인해 바인딩 시간 오류가 발생 하지 않습니다.The failure of type inference, in and of itself, does not cause a binding-time error. 그러나 오버 로드 확인에서 적용 가능한 메서드를 찾지 못하면 바인딩 시간 오류가 발생 하는 경우가 많습니다.However, it often leads to a binding-time error when overload resolution then fails to find any applicable methods.

제공 된 인수 개수가 메서드의 매개 변수 개수와 다르면 유추는 즉시 실패 합니다.If the supplied number of arguments is different than the number of parameters in the method, then inference immediately fails. 그렇지 않으면 제네릭 메서드의 서명이 다음과 같다고 가정 합니다.Otherwise, assume that the generic method has the following signature:

Tr M<X1,...,Xn>(T1 x1, ..., Tm xm)

@No__t 폼의 메서드 호출을 사용 하 여-0 형식 유추 작업은-@no__t 2 @no__t 각 형식 매개 변수에 대해-1 @no__t 고유한 형식 인수를 찾는 것입니다.With a method call of the form M(E1...Em) the task of type inference is to find unique type arguments S1...Sn for each of the type parameters X1...Xn so that the call M<S1...Sn>(E1...Em) becomes valid.

유추 프로세스가 진행 되는 동안 각 형식 매개 변수 Xi은 특정 형식 Si로 고정 되거나 연결 된 범위집합을 사용 하 여 고정 되지 않습니다.During the process of inference each type parameter Xi is either fixed to a particular type Si or unfixed with an associated set of bounds. 각 범위는-0 @no__t 일부 형식입니다.Each of the bounds is some type T. 처음에는 각 형식 변수 Xi이 빈 범위 집합으로 고정 되지 않습니다.Initially each type variable Xi is unfixed with an empty set of bounds.

형식 유추는 단계에서 발생 합니다.Type inference takes place in phases. 각 단계는 이전 단계의 결과에 따라 더 많은 형식 변수에 대 한 형식 인수를 유추 하려고 합니다.Each phase will try to infer type arguments for more type variables based on the findings of the previous phase. 첫 번째 단계에서는 몇 가지 초기 추론 범위를 지정 하는 반면 두 번째 단계에서는 형식 변수를 특정 형식으로 수정 하 고 추가 범위를 유추 합니다.The first phase makes some initial inferences of bounds, whereas the second phase fixes type variables to specific types and infers further bounds. 두 번째 단계를 여러 번 반복 해야 할 수도 있습니다.The second phase may have to be repeated a number of times.

참고: 형식 유추는 제네릭 메서드를 호출 하는 경우에만 발생 합니다.Note: Type inference takes place not only when a generic method is called. 메서드 그룹 변환에 대 한 형식 유추는 메서드 그룹의 변환에 대 한 형식 유추식 집합의가장 일반적인 형식 찾기에 설명 되어 있습니다.Type inference for conversion of method groups is described in Type inference for conversion of method groups and finding the best common type of a set of expressions is described in Finding the best common type of a set of expressions.

첫 번째 단계The first phase

각 메서드 인수 Ei:For each of the method arguments Ei:

  • @No__t-0이 익명 함수 이면 Ei에서 Ti명시적 매개 변수 형식 유추 (명시적 매개 변수 형식 추론)가 수행 됩니다.If Ei is an anonymous function, an explicit parameter type inference (Explicit parameter type inferences) is made from Ei to Ti
  • 그렇지 않고 Ei의 형식이 U이 고 xi가 값 매개 변수 이면 U 에서 Ti 더 낮은 바인딩된 유추가 수행 됩니다.Otherwise, if Ei has a type U and xi is a value parameter then a lower-bound inference is made from U to Ti.
  • 그렇지 않고 Ei의 형식이 U이 고 xiref 또는 out 매개 변수인 경우 U 에서 Ti 정확히 유추 됩니다.Otherwise, if Ei has a type U and xi is a ref or out parameter then an exact inference is made from U to Ti.
  • 그렇지 않으면이 인수에 대해 유추가 수행 되지 않습니다.Otherwise, no inference is made for this argument.

두 번째 단계The second phase

두 번째 단계는 다음과 같이 진행 됩니다.The second phase proceeds as follows:

  • 고정 되지 않은 모든 형식 변수 @no__t (종속성) 에 의존 하지 않는 Xj는 고정 (수정) 됩니다.All unfixed type variables Xi which do not depend on (Dependence) any Xj are fixed (Fixing).
  • 이러한 형식 변수가 없으면 수정 되지 않은 모든 형식 변수 Xi은 다음 모두에 적용 됩니다.If no such type variables exist, all unfixed type variables Xi are fixed for which all of the following hold:
    • 1 @no__t에 종속 된 Xj의 형식 변수가 하나 이상 있습니다.There is at least one type variable Xj that depends on Xi
    • Xi에 비어 있지 않은 범위 집합이 있습니다.Xi has a non-empty set of bounds
  • 이러한 형식 변수가 없고 여전히 고정 되지 않은 형식 변수가 있으면 형식 유추가 실패 합니다.If no such type variables exist and there are still unfixed type variables, type inference fails.
  • 그렇지 않고, 더 이상 고정 되지 않은 형식 변수가 없으면 형식 유추가 성공 합니다.Otherwise, if no further unfixed type variables exist, type inference succeeds.
  • 그렇지 않은 경우 Ei모든 인수에 대해 해당하는 매개 변수 Ti 형식으로-0 합니다 .이 경우 출력 형식(출력 형식)은 고정되지 않은 형식 변수 Xj를 포함하지만 입력 형식(입력 형식)은 그렇지 않습니다. 출력 형식 유추(output type 추론) Ei 에서 Ti로 로설정됩니다.Otherwise, for all arguments Ei with corresponding parameter type Ti where the output types (Output types) contain unfixed type variables Xj but the input types (Input types) do not, an output type inference (Output type inferences) is made from Ei to Ti. 그런 다음 두 번째 단계가 반복 됩니다.Then the second phase is repeated.

입력 형식Input types

@No__t-0이 메서드 그룹 이거나 암시적으로 형식이 지정 된 익명 함수이 고 T이 대리자 형식 또는 식 트리 형식이 면 T의 모든 매개 변수 형식은 T 형식의 입력 형식인 E입니다.If E is a method group or implicitly typed anonymous function and T is a delegate type or expression tree type then all the parameter types of T are input types of E with type T.

출력 형식Output types

@No__t-0이 메서드 그룹 또는 익명 함수이 고 T이 대리자 형식 또는 식 트리 형식이 면 T의 반환 형식은 T 형식의 E 의 출력 형식 입니다.If E is a method group or an anonymous function and T is a delegate type or expression tree type then the return type of T is an output type of E with type T.

종속성Dependence

고정 되지 않은 형식 변수 Xi은 고정 되지 않은 형식 @no__t 변수에 직접 종속 됩니다. Tk @no__t 형식의 일부 인수 Ek의 경우 Tk 형식으로 Ek입력 형식 에서 발생 하 고 0 유형 3 인 2의 출력 유형입니다.An unfixed type variable Xi depends directly on an unfixed type variable Xj if for some argument Ek with type Tk Xj occurs in an input type of Ek with type Tk and Xi occurs in an output type of Ek with type Tk.

@no__t--3 Xi 에 직접 의존 하거나 XiXk 에 직접 종속 되는 경우 @no__t-@no__t 2 따라 1 에 의존 합니다.Xj depends on Xi if Xj depends directly on Xi or if Xi depends directly on Xk and Xk depends on Xj. 따라서 "종속"은 전이적 이지만 "직접 종속"의 반사 클로저는 그렇지 않습니다.Thus "depends on" is the transitive but not reflexive closure of "depends directly on".

출력 형식 추론Output type inferences

출력 형식 유추 는 식 에서 다음과 같은 방식으로-2 @no__t 형식으로 @no__t 합니다.An output type inference is made from an expression E to a type T in the following way:

  • @No__t-0은 유추 된 반환 형식 U (유추 된 반환 형식)을 사용 하는 익명 함수이 고, T은 반환 형식이 Tb 인 대리자 형식 또는 식 트리 형식이 며, 낮은 바인딩 유추 (하한값 추론)입니다. U 에서 0 으로 설정 됩니다.If E is an anonymous function with inferred return type U (Inferred return type) and T is a delegate type or expression tree type with return type Tb, then a lower-bound inference (Lower-bound inferences) is made from U to Tb.
  • 그렇지 않고 E이 메서드 그룹이 고 T은 매개 변수 형식이 T1...Tk이 고 반환 @no__t 형식이-3 인 대리자 형식 또는 식 트리 형식이 며, T1...Tk 형식으로 E의 오버 로드 확인은 반환 형식이 U 인 단일 메서드를 생성 합니다. 그런 다음 U 에서 1 낮은 바인딩 유추가 수행 됩니다.Otherwise, if E is a method group and T is a delegate type or expression tree type with parameter types T1...Tk and return type Tb, and overload resolution of E with the types T1...Tk yields a single method with return type U, then a lower-bound inference is made from U to Tb.
  • 그렇지 않고 E이 @no__t 형식이-1 인 식인 경우 U에서 T 으로 하한값 이 적용 됩니다.Otherwise, if E is an expression with type U, then a lower-bound inference is made from U to T.
  • 그렇지 않으면 추론가 수행 되지 않습니다.Otherwise, no inferences are made.

명시적 매개 변수 형식 추론Explicit parameter type inferences

명시적 매개 변수 형식 유추 는 다음과 같은 방식으로 식 에서 -2를 @no__t 형식 으로 @no__t 합니다.An explicit parameter type inference is made from an expression E to a type T in the following way:

  • @No__t-0이 명시적으로 형식화 된 익명 함수 @no__t 매개 변수 형식이-1이 고, T가 매개 변수 형식이 V1...Vk 인 대리자 형식 또는 식 트리 형식인 경우 각 @no__t에 대해 정확한 유추 (정확한 추론)가 수행 됩니다. Ui에서 해당 U1...Uk0입니다.If E is an explicitly typed anonymous function with parameter types U1...Uk and T is a delegate type or expression tree type with parameter types V1...Vk then for each Ui an exact inference (Exact inferences) is made from Ui to the corresponding Vi.

정확한 추론Exact inferences

형식에 대 한 정확한 유추 는 다음과 같이 @no__t -2 형식 V입니다.An exact inference from a type U to a type V is made as follows:

  • @No__t-0이 고정 되지 *않은 @no__t-* 2 중 하나 이면-3 @no__t Xi의 정확한 범위 집합에 추가 됩니다.If V is one of the unfixed Xi then U is added to the set of exact bounds for Xi.

  • 그렇지 않으면 V1...Vk을 설정 하 고 U1...Uk은 다음 경우에 적용 되는지 확인 하 여 결정 됩니다.Otherwise, sets V1...Vk and U1...Uk are determined by checking if any of the following cases apply:

    • V은-1 @no__t 배열 형식이 고, U는 동일한 순위의 배열 형식 U1[...]입니다.V is an array type V1[...] and U is an array type U1[...] of the same rank
    • V은 형식 V1?이 고 UU1? 형식입니다.V is the type V1? and U is the type U1?
    • V은 생성 된 형식 C<V1...Vk> 이며 U는 생성 된 형식 C<U1...Uk>입니다.V is a constructed type C<V1...Vk>and U is a constructed type C<U1...Uk>

    이러한 경우에 적용 되는 경우에는 각 Ui 에서 해당 하는 Vi 정확히 유추 됩니다.If any of these cases apply then an exact inference is made from each Ui to the corresponding Vi.

  • 그렇지 않으면 추론가 수행 되지 않습니다.Otherwise no inferences are made.

낮은 바인딩 추론Lower-bound inferences

형식 @no__t -2 에서 @no__t 형식으로 하한값 은 다음과 같이 결정 됩니다.A lower-bound inference from a type U to a type V is made as follows:

  • @No__t-0이 고정 되지 *않은 @no__t-* 2 중 하나 이면-3 @no__t Xi의 하한값 집합에 추가 됩니다.If V is one of the unfixed Xi then U is added to the set of lower bounds for Xi.

  • 그렇지 않고 V이 형식 V1?이 고 U의 형식이 U1? 이면 U1에서 V1로 더 낮은 바인딩 유추가 수행 됩니다.Otherwise, if V is the type V1?and U is the type U1? then a lower bound inference is made from U1 to V1.

  • 그렇지 않으면 U1...Uk을 설정 하 고 V1...Vk은 다음 경우에 적용 되는지 확인 하 여 결정 됩니다.Otherwise, sets U1...Uk and V1...Vk are determined by checking if any of the following cases apply:

    • V은 배열 형식이 V1[...]이 고 U는 배열 형식 U1[...] (또는 유효 기본 형식이 U1[...]) 인 형식 매개 변수가 동일한 차수의 배열 형식입니다.V is an array type V1[...] and U is an array type U1[...] (or a type parameter whose effective base type is U1[...]) of the same rank

    • VIEnumerable<V1>, ICollection<V1> 또는 IList<V1> 중 하나이 고, U는 1 차원 배열 형식 U1[] (또는 유효 기본 형식이 U1[] 인 형식 매개 변수)입니다.V is one of IEnumerable<V1>, ICollection<V1> or IList<V1> and U is a one-dimensional array type U1[](or a type parameter whose effective base type is U1[])

    • V은 생성 된 클래스, 구조체, 인터페이스 또는 대리자 형식 C<V1...Vk> 이며 @no__t,이 @no__t는-3 (또는-4가 형식 매개 변수, 유효한 기본 클래스 또는 유효한 인터페이스 집합의 모든 멤버)와 같은 고유한 형식이 C<U1...Uk>입니다. 는 (직접 또는 간접적으로)에서 상속 하거나 (직접 또는 간접적으로) C<U1...Uk>를 구현 합니다.V is a constructed class, struct, interface or delegate type C<V1...Vk> and there is a unique type C<U1...Uk> such that U (or, if U is a type parameter, its effective base class or any member of its effective interface set) is identical to, inherits from (directly or indirectly), or implements (directly or indirectly) C<U1...Uk>.

      "고유성" 제한 사항은 사례 @no__t 인터페이스에서-0을 사용 하는 것을 의미 합니다.-3 X 또는 Y 일 수 있으므로 U에서 C<T>로 유추할 때 유추가 수행 되지 않습니다.(The "uniqueness" restriction means that in the case interface C<T> {} class U: C<X>, C<Y> {}, then no inference is made when inferring from U to C<T> because U1 could be X or Y.)

    이러한 경우에 적용 되는 경우 다음과 같이 각 Ui 에서 해당 Vi으로의 유추가 수행 됩니다.If any of these cases apply then an inference is made from each Ui to the corresponding Vi as follows:

    • @No__t-0을 참조 형식으로 알 수 없으면 정확한 유추가 수행 됩니다.If Ui is not known to be a reference type then an exact inference is made
    • 그렇지 않고 U이 배열 형식이 면 낮은 바인딩 유추가 수행 됩니다.Otherwise, if U is an array type then a lower-bound inference is made
    • 그렇지 않고 VC<V1...Vk> 이면 유추는 C의 i 번째 형식 매개 변수에 따라 달라 집니다.Otherwise, if V is C<V1...Vk> then inference depends on the i-th type parameter of C:
      • 공변 (covariant) 인 경우에는 더 낮은 바인딩 유추가 수행 됩니다.If it is covariant then a lower-bound inference is made.
      • 반공 변 (contravariant) 인 경우에는 상한을 유추 합니다.If it is contravariant then an upper-bound inference is made.
      • 고정 이면 정확한 유추가 수행 됩니다.If it is invariant then an exact inference is made.
  • 그렇지 않으면 추론가 수행 되지 않습니다.Otherwise, no inferences are made.

상한 추론Upper-bound inferences

형식 U에서 @no__t 형식으로 상한 유추가 다음과 같이 수행 됩니다.An upper-bound inference from a type U to a type V is made as follows:

  • @No__t-0이 고정 되지 않은 Xi 중 하나 이면-3 @no__t @no__t- 4의 상한 집합에 추가 됩니다.If V is one of the unfixed Xi then U is added to the set of upper bounds for Xi.

  • 그렇지 않으면 V1...Vk을 설정 하 고 U1...Uk은 다음 경우에 적용 되는지 확인 하 여 결정 됩니다.Otherwise, sets V1...Vk and U1...Uk are determined by checking if any of the following cases apply:

    • U은-1 @no__t 배열 형식이 고, V는 동일한 순위의 배열 형식 V1[...]입니다.U is an array type U1[...] and V is an array type V1[...] of the same rank

    • UIEnumerable<Ue>, ICollection<Ue> 또는 IList<Ue> 중 하나이 고, V는 1 차원 배열 형식인 Ve[]입니다.U is one of IEnumerable<Ue>, ICollection<Ue> or IList<Ue> and V is a one-dimensional array type Ve[]

    • U은 형식 U1?이 고 VV1? 형식입니다.U is the type U1? and V is the type V1?

    • U은 생성 된 클래스, 구조체, 인터페이스 또는 대리자 형식 C<U1...Uk>이 고 V는와 동일한 클래스, 구조체, 인터페이스 또는 대리자 형식입니다 .는 (직접 또는 간접적으로) 상속 하거나 직접 또는 간접적으로 고유 형식을 구현 합니다.-3 @no__tU is constructed class, struct, interface or delegate type C<U1...Uk> and V is a class, struct, interface or delegate type which is identical to, inherits from (directly or indirectly), or implements (directly or indirectly) a unique type C<V1...Vk>

      "고유성" 제한은 interface C<T>{} class V<Z>: C<X<Z>>, C<Y<Z>>{} 인 경우 C<U1>에서 V<Q>로 유추할 때 유추가 수행 되지 않음을 의미 합니다.(The "uniqueness" restriction means that if we have interface C<T>{} class V<Z>: C<X<Z>>, C<Y<Z>>{}, then no inference is made when inferring from C<U1> to V<Q>. 추론는 U1에서 X<Q> 또는 Y<Q>)로 구성 되지 않습니다.Inferences are not made from U1 to either X<Q> or Y<Q>.)

    이러한 경우에 적용 되는 경우 다음과 같이 각 Ui 에서 해당 Vi으로의 유추가 수행 됩니다.If any of these cases apply then an inference is made from each Ui to the corresponding Vi as follows:

    • @No__t-0을 참조 형식으로 알 수 없으면 정확한 유추가 수행 됩니다.If Ui is not known to be a reference type then an exact inference is made
    • 그렇지 않고 V이 배열 형식이 면 상한 유추가 수행 됩니다.Otherwise, if V is an array type then an upper-bound inference is made
    • 그렇지 않고 UC<U1...Uk> 이면 유추는 C의 i 번째 형식 매개 변수에 따라 달라 집니다.Otherwise, if U is C<U1...Uk> then inference depends on the i-th type parameter of C:
      • 공변 (covariant) 인 경우에는 상한을 유추 합니다.If it is covariant then an upper-bound inference is made.
      • 반공 변 (contravariant) 인 경우에는 더 낮은 바인딩 유추가 수행 됩니다.If it is contravariant then a lower-bound inference is made.
      • 고정 이면 정확한 유추가 수행 됩니다.If it is invariant then an exact inference is made.
  • 그렇지 않으면 추론가 수행 되지 않습니다.Otherwise, no inferences are made.

수정Fixing

범위 집합이 있는 고정 되지 않은 형식 변수 @no__t- 1은 다음과 같이 고정 됩니다.An unfixed type variable Xi with a set of bounds is fixed as follows:

  • 후보 형식 Uj은 @no__t의 범위 집합에 있는 모든 형식의 집합으로 시작 합니다.The set of candidate types Uj starts out as the set of all types in the set of bounds for Xi.
  • 그런 다음 Xi에 대 한 각 범위를 차례로 검사 합니다. @No__t의 정확히 바인딩된 Xi의 경우-1 U과 동일 하지 않은 모든 @no__t 형식이 후보 집합에서 제거 됩니다.We then examine each bound for Xi in turn: For each exact bound U of Xi all types Uj which are not identical to U are removed from the candidate set. @No__t-4에서 암시적 변환이 발생 하지 않는 각 하 한 Xi의 @no__t 모든 @no__t 형식은 후보 집합에서 제거 됩니다.For each lower bound U of Xi all types Uj to which there is not an implicit conversion from U are removed from the candidate set. @No__t의 상한 U은-1의 모든 형식 UjU로 암시적으로 변환할 수 없습니다 .For each upper bound U of Xi all types Uj from which there is not an implicit conversion to U are removed from the candidate set.
  • 나머지 후보 형식에 Uj은 다른 후보 형식으로의 암시적 변환이 있는 고유한 형식이 V이 고, XiV으로 고정 됩니다.If among the remaining candidate types Uj there is a unique type V from which there is an implicit conversion to all the other candidate types, then Xi is fixed to V.
  • 그렇지 않으면 형식 유추가 실패 합니다.Otherwise, type inference fails.

유추 된 반환 형식Inferred return type

익명 함수의 유추 된 반환 형식 F은 형식 유추 및 오버 로드 확인 중에 사용 됩니다.The inferred return type of an anonymous function F is used during type inference and overload resolution. 유추 된 반환 형식은 모든 매개 변수 형식이 명시적으로 지정 된 경우에만 확인할 수 있습니다 .이 함수는 무명 함수 변환을 통해 제공 되거나 바깥쪽 제네릭에 대 한 형식 유추 중에 유추 됩니다. 메서드 호출입니다.The inferred return type can only be determined for an anonymous function where all parameter types are known, either because they are explicitly given, provided through an anonymous function conversion or inferred during type inference on an enclosing generic method invocation.

유추 된 결과 형식은 다음과 같이 결정 됩니다.The inferred result type is determined as follows:

  • @No__t-0의 본문이 형식의 식인 경우 F의 유추 된 결과 형식이 해당 식의 형식입니다.If the body of F is an expression that has a type, then the inferred result type of F is the type of that expression.
  • @No__t-0의 본문이 블록 이 고 블록의 return 문의 식 집합에 가장 적합 한 @no__t 일반 형식인 경우-3 (식 집합의 최고 공용 형식 찾기)은 유추 된 결과 형식 F는 @no__t입니다.If the body of F is a block and the set of expressions in the block's return statements has a best common type T (Finding the best common type of a set of expressions), then the inferred result type of F is T.
  • 그렇지 않으면 F에 대 한 결과 형식을 유추할 수 없습니다.Otherwise, a result type cannot be inferred for F.

유추 된 반환 형식은 다음과 같이 결정 됩니다.The inferred return type is determined as follows:

  • @No__t-0이 비동기이 고 F의 본문이 nothing (식 분류)으로 분류 된 식 이거나 return 문에 식이 없는 문 블록 인 경우 유추 된 반환 형식은 System.Threading.Tasks.Task입니다.If F is async and the body of F is either an expression classified as nothing (Expression classifications), or a statement block where no return statements have expressions, the inferred return type is System.Threading.Tasks.Task
  • @No__t-0이 비동기이 고 유추 된 결과 형식 T 이면 유추 된 반환 형식은-2 @no__t 됩니다.If F is async and has an inferred result type T, the inferred return type is System.Threading.Tasks.Task<T>.
  • @No__t-0이 비동기가 아니고 유추 된 결과 형식 T 이면 유추 된 반환 형식은 T입니다.If F is non-async and has an inferred result type T, the inferred return type is T.
  • 그렇지 않으면 F에 대해 반환 형식을 유추할 수 없습니다.Otherwise a return type cannot be inferred for F.

익명 함수를 포함 하는 형식 유추의 예로 System.Linq.Enumerable 클래스에서 선언 된 Select 확장 메서드를 참조 하세요.As an example of type inference involving anonymous functions, consider the Select extension method declared in the System.Linq.Enumerable class:

namespace System.Linq
{
    public static class Enumerable
    {
        public static IEnumerable<TResult> Select<TSource,TResult>(
            this IEnumerable<TSource> source,
            Func<TSource,TResult> selector)
        {
            foreach (TSource element in source) yield return selector(element);
        }
    }
}

@No__t-1 절을 사용 하 여 System.Linq 네임 스페이스를 가져오고 string 형식의 Name 속성이 Customer 인 클래스를 지정 하는 경우 Select 메서드를 사용 하 여 고객 목록의 이름을 선택할 수 있습니다.Assuming the System.Linq namespace was imported with a using clause, and given a class Customer with a Name property of type string, the Select method can be used to select the names of a list of customers:

List<Customer> customers = GetCustomerList();
IEnumerable<string> names = customers.Select(c => c.Name);

@No__t-1의 확장 메서드 호출 (확장 메서드호출)은 호출을 정적 메서드 호출로 다시 작성 하 여 처리 됩니다.The extension method invocation (Extension method invocations) of Select is processed by rewriting the invocation to a static method invocation:

IEnumerable<string> names = Enumerable.Select(customers, c => c.Name);

형식 인수를 명시적으로 지정 하지 않았으므로 형식 유추를 사용 하 여 형식 인수를 유추 합니다.Since type arguments were not explicitly specified, type inference is used to infer the type arguments. 첫째, customers 인수는 source 매개 변수와 관련 되어 TCustomer으로 유추 합니다.First, the customers argument is related to the source parameter, inferring T to be Customer. 그런 다음 위에 설명 된 익명 함수 형식 유추 프로세스를 사용 하 여 c에는 Customer 형식이 지정 되 고 식 c.Nameselector 매개 @no__t 변수의 반환 형식과 관련이 있습니다.Then, using the anonymous function type inference process described above, c is given type Customer, and the expression c.Name is related to the return type of the selector parameter, inferring S to be string. 따라서 호출은와 동일 합니다.Thus, the invocation is equivalent to

Sequence.Select<Customer,string>(customers, (Customer c) => c.Name)

결과의 형식은 IEnumerable<string>입니다.and the result is of type IEnumerable<string>.

다음 예제에서는 익명 함수 형식 유추를 사용 하 여 제네릭 메서드 호출에서 인수 사이에 형식 정보를 "flow" 하는 방법을 보여 줍니다.The following example demonstrates how anonymous function type inference allows type information to "flow" between arguments in a generic method invocation. 다음 메서드가 제공 됩니다.Given the method:

static Z F<X,Y,Z>(X value, Func<X,Y> f1, Func<Y,Z> f2) {
    return f2(f1(value));
}

호출에 대 한 형식 유추:Type inference for the invocation:

double seconds = F("1:15:30", s => TimeSpan.Parse(s), t => t.TotalSeconds);

다음과 같이 진행 합니다. 먼저 인수 "1:15:30"value 매개 변수와 관련 되며,-2 string @no__t 되도록 유추 합니다.proceeds as follows: First, the argument "1:15:30" is related to the value parameter, inferring X to be string. 그런 다음, 첫 번째 익명 함수의 매개 변수 s은 유추 된 형식 string로 지정 되 고,-2 @no__t 식은-3 @no__t의 반환 형식과 관련이 있습니다. 즉,-4는 System.TimeSpan로 유추 됩니다.Then, the parameter of the first anonymous function, s, is given the inferred type string, and the expression TimeSpan.Parse(s) is related to the return type of f1, inferring Y to be System.TimeSpan. 마지막으로 두 번째 익명 함수 (t)의 매개 변수에 유추 된 형식 System.TimeSpan이 지정 되 고 식 t.TotalSeconds가-3 @no__t의 반환 형식과 관련이 있습니다. 즉,-4는 double로 유추 됩니다.Finally, the parameter of the second anonymous function, t, is given the inferred type System.TimeSpan, and the expression t.TotalSeconds is related to the return type of f2, inferring Z to be double. 따라서 호출 결과의 형식은 double입니다.Thus, the result of the invocation is of type double.

메서드 그룹 변환에 대 한 형식 유추Type inference for conversion of method groups

제네릭 메서드를 호출 하는 것과 마찬가지로 제네릭 메서드를 포함 하는 메서드 @no__t 그룹이 지정 된 대리자 형식 D (메서드 그룹 변환)로 변환 되는 경우에도 형식 유추를 적용 해야 합니다.Similar to calls of generic methods, type inference must also be applied when a method group M containing a generic method is converted to a given delegate type D (Method group conversions). 지정 된 메서드Given a method

Tr M<X1...Xn>(T1 x1 ... Tm xm)

그리고 메서드 그룹 @no__t 대리자 형식에 할당 되는-1 D 형식 유추 작업은 식의 형식 인수 S1...Sn를 찾는 것입니다.and the method group M being assigned to the delegate type D the task of type inference is to find type arguments S1...Sn so that the expression:

M<S1...Sn>

D과 호환 됩니다 (대리자 선언).becomes compatible (Delegate declarations) with D.

제네릭 메서드 호출에 대 한 형식 유추 알고리즘과 달리이 경우에는 인수 없이 인수 형식만있습니다.Unlike the type inference algorithm for generic method calls, in this case there are only argument types, no argument expressions. 특히 익명 함수는 없으며 유추의 여러 단계가 필요 하지 않습니다.In particular, there are no anonymous functions and hence no need for multiple phases of inference.

대신 모든 Xi은 고정 되지 않은 것으로간주 되 고, D의-4 @no__t 각 인수 형식 에서 해당 하는 매개 변수 형식 (MTj) 으로하한값 이 적용 됩니다.Instead, all Xi are considered unfixed, and a lower-bound inference is made from each argument type Uj of D to the corresponding parameter type Tj of M. @No__t 중 하나에 대해 범위를 찾을 수 없는 경우 형식 유추가 실패 합니다.If for any of the Xi no bounds were found, type inference fails. 그렇지 않으면 모든 Xi은 형식 유추의 결과인 해당 Si고정 됩니다.Otherwise, all Xi are fixed to corresponding Si, which are the result of type inference.

식 집합의 가장 일반적인 형식 찾기Finding the best common type of a set of expressions

식 집합에 대해 공용 형식을 유추 해야 하는 경우도 있습니다.In some cases, a common type needs to be inferred for a set of expressions. 특히 암시적으로 형식화 된 배열의 요소 형식과 블록 본문이 있는 익명 함수의 반환 형식이 이러한 방식으로 발견 됩니다.In particular, the element types of implicitly typed arrays and the return types of anonymous functions with block bodies are found in this way.

식 집합이 지정 된 경우, E1...Em이 유추는 메서드 호출과 동일 해야 합니다.Intuitively, given a set of expressions E1...Em this inference should be equivalent to calling a method

Tr M<X>(X x1 ... X xm)

Ei을 인수로 사용 합니다.with the Ei as arguments.

보다 정확 하 게 유추는 고정 되지 않은 형식 변수 X로 시작 합니다.More precisely, the inference starts out with an unfixed type variable X. 그런 다음 추론 출력 형식은Ei 에서 X 생성 됩니다.Output type inferences are then made from each Ei to X. 마지막으로 X고정 되 고, 성공 하면 결과 형식 S가 식의 가장 적합 한 공용 형식이 됩니다.Finally, X is fixed and, if successful, the resulting type S is the resulting best common type for the expressions. 이러한 @no__t 없는 경우 식에 가장 적합 한 공용 형식이 없습니다.If no such S exists, the expressions have no best common type.

오버로드 해결Overload resolution

오버 로드 확인은 인수 목록과 후보 함수 멤버 집합이 지정 된 경우 호출할 최상의 함수 멤버를 선택 하기 위한 바인딩 시간 메커니즘입니다.Overload resolution is a binding-time mechanism for selecting the best function member to invoke given an argument list and a set of candidate function members. 오버 로드 확인은 내에서 C#다음과 같은 고유한 컨텍스트에서 호출할 함수 멤버를 선택 합니다.Overload resolution selects the function member to invoke in the following distinct contexts within C#:

이러한 각 컨텍스트는 위에 나열 된 섹션에 자세히 설명 된 대로 고유한 방식으로 후보 함수 멤버 집합과 인수 목록을 정의 합니다.Each of these contexts defines the set of candidate function members and the list of arguments in its own unique way, as described in detail in the sections listed above. 예를 들어 메서드 호출에 대 한 후보 집합에 override (멤버 조회)로 표시 된 메서드는 포함 되지 않으며, 파생 클래스의 메서드 (메서드 호출)가 적용 되는 경우 기본 클래스의 메서드는 후보가 아닙니다.For example, the set of candidates for a method invocation does not include methods marked override (Member lookup), and methods in a base class are not candidates if any method in a derived class is applicable (Method invocations).

후보 함수 멤버와 인수 목록이 식별 되 면 모든 경우에서 최상의 함수 멤버를 선택할 수 있습니다.Once the candidate function members and the argument list have been identified, the selection of the best function member is the same in all cases:

  • 해당 하는 후보 함수 멤버 집합이 지정 된 경우 해당 집합의 최상의 함수 멤버가 배치 됩니다.Given the set of applicable candidate function members, the best function member in that set is located. 집합에 함수 멤버가 하나만 있는 경우 해당 함수 멤버가 최상의 함수 멤버입니다.If the set contains only one function member, then that function member is the best function member. 그렇지 않으면 최상의 함수 멤버는 지정 된 인수 목록과 관련 된 다른 모든 함수 멤버 보다 더 나은 함수 멤버입니다. 모든 함수 멤버는 규칙을 사용 하 여 다른 모든 함수 멤버와 비교 하 여 더 나은 함수를 제공 합니다. 멤버.Otherwise, the best function member is the one function member that is better than all other function members with respect to the given argument list, provided that each function member is compared to all other function members using the rules in Better function member. 다른 모든 함수 멤버 보다 더 적합 한 함수 멤버가 정확히 하나가 아니면 함수 멤버 호출이 모호 하 고 바인딩 타임 오류가 발생 합니다.If there is not exactly one function member that is better than all other function members, then the function member invocation is ambiguous and a binding-time error occurs.

다음 섹션에서는 적용 가능한 함수 멤버더 나은 함수 멤버의 정확한 의미를 정의 합니다.The following sections define the exact meanings of the terms applicable function member and better function member.

적용 가능한 함수 멤버Applicable function member

함수 멤버는 다음 모두에 해당 하는 경우-1 @no__t 인수 목록과 관련 된 적용 가능한 함수 멤버 라고 합니다.A function member is said to be an applicable function member with respect to an argument list A when all of the following are true:

  • @No__t의 각 인수는 해당 매개 변수에설명 된 함수 멤버 선언에 있는 매개 변수에 해당 하 고 인수가 없는 매개 변수는 선택적 매개 변수입니다.Each argument in A corresponds to a parameter in the function member declaration as described in Corresponding parameters, and any parameter to which no argument corresponds is an optional parameter.
  • @No__t-0의 각 인수에 대해 인수의 매개 변수 전달 모드 (즉, 값, ref 또는 out)는 해당 매개 변수의 매개 변수 전달 모드와 동일 합니다.For each argument in A, the parameter passing mode of the argument (i.e., value, ref, or out) is identical to the parameter passing mode of the corresponding parameter, and
    • 값 매개 변수 또는 매개 변수 배열의 경우 인수에서 해당 매개 변수의 형식에 대 한 암시적 변환 (암시적 변환)이 존재 하거나for a value parameter or a parameter array, an implicit conversion (Implicit conversions) exists from the argument to the type of the corresponding parameter, or
    • ref 또는 out 매개 변수의 경우 인수의 형식은 해당 하는 매개 변수의 형식과 동일 합니다.for a ref or out parameter, the type of the argument is identical to the type of the corresponding parameter. @No__t-0 또는 out 매개 변수는 전달 된 인수에 대 한 별칭입니다.After all, a ref or out parameter is an alias for the argument passed.

매개 변수 배열을 포함 하는 함수 멤버의 경우 함수 멤버가 위의 규칙에 따라 적용 되는 경우 일반 형식으로 적용 되는 것으로 간주 됩니다.For a function member that includes a parameter array, if the function member is applicable by the above rules, it is said to be applicable in its normal form. 매개 변수 배열을 포함 하는 함수 멤버를 일반 형식으로 적용할 수 없는 경우 대신 함수 멤버를 확장 된 형식으로 적용할 수 있습니다.If a function member that includes a parameter array is not applicable in its normal form, the function member may instead be applicable in its expanded form:

  • 확장 된 폼은 인수 @no__t 목록에 있는 인수의 개수가 총 개수와 일치 하는 매개 변수 배열의 요소 형식에 대 한 0 개 이상의 값 매개 변수로 함수 멤버 선언에서 매개 변수 배열을 대체 하 여 생성 됩니다. 매개 변수입니다.The expanded form is constructed by replacing the parameter array in the function member declaration with zero or more value parameters of the element type of the parameter array such that the number of arguments in the argument list A matches the total number of parameters. @No__t-0에 함수 멤버 선언에 있는 고정 매개 변수 수보다 더 작은 인수가 있는 경우 함수 멤버의 확장 된 형식을 생성할 수 없으므로 해당 되지 않습니다.If A has fewer arguments than the number of fixed parameters in the function member declaration, the expanded form of the function member cannot be constructed and is thus not applicable.
  • 그렇지 않은 경우에는 @no__t의 각 인수에 대해 인수의 매개 변수 전달 모드가 해당 매개 변수의 매개 변수 전달 모드와 동일한 경우 확장 된 형식이 적용 됩니다.Otherwise, the expanded form is applicable if for each argument in A the parameter passing mode of the argument is identical to the parameter passing mode of the corresponding parameter, and
    • 확장에 의해 생성 된 고정 값 매개 변수 또는 값 매개 변수의 경우 인수 형식에서 해당 매개 변수의 형식으로 암시적 변환 (암시적 변환)이 존재 하거나for a fixed value parameter or a value parameter created by the expansion, an implicit conversion (Implicit conversions) exists from the type of the argument to the type of the corresponding parameter, or
    • ref 또는 out 매개 변수의 경우 인수의 형식은 해당 하는 매개 변수의 형식과 동일 합니다.for a ref or out parameter, the type of the argument is identical to the type of the corresponding parameter.

더 나은 함수 멤버Better function member

더 나은 함수 멤버를 결정 하기 위해, 제거 된 인수 목록 A는 원래 인수 목록에 나타나는 순서 대로 인수 식만 포함 하 여 생성 됩니다.For the purposes of determining the better function member, a stripped-down argument list A is constructed containing just the argument expressions themselves in the order they appear in the original argument list.

각 후보 함수 멤버에 대 한 매개 변수 목록은 다음과 같은 방식으로 생성 됩니다.Parameter lists for each of the candidate function members are constructed in the following way:

  • 확장 된 형태는 함수 멤버가 확장 된 형식에만 적용 되는 경우에 사용 됩니다.The expanded form is used if the function member was applicable only in the expanded form.
  • 해당 인수를 포함 하지 않는 선택적 매개 변수는 매개 변수 목록에서 제거 됩니다.Optional parameters with no corresponding arguments are removed from the parameter list
  • 매개 변수는 인수 목록에 있는 해당 인수와 동일한 위치에서 발생 하도록 다시 정렬 됩니다.The parameters are reordered so that they occur at the same position as the corresponding argument in the argument list.

인수 @no__t 목록을 지정 하는 경우-0은 인수 식 집합에-1 @no__t 하 고 해당 하는 두 개의 해당 함수 멤버 MpMq은 매개 변수 형식이 {P1, P2, ..., Pn}{Q1, Q2, ..., Qn} 인 경우 Mq 보다 더 나은 함수 멤버로 정의 됩니다.Given an argument list A with a set of argument expressions {E1, E2, ..., En} and two applicable function members Mp and Mq with parameter types {P1, P2, ..., Pn} and {Q1, Q2, ..., Qn}, Mp is defined to be a better function member than Mq if

  • 각 인수에 대해 Ex에서 Qx로의 암시적 변환은 Ex에서 Px으로의 암시적 변환 보다 더 낫습니다.for each argument, the implicit conversion from Ex to Qx is not better than the implicit conversion from Ex to Px, and
  • 하나 이상의 인수에 대해 Ex에서 Px로 변환 하는 것은 Ex에서 Qx으로 변환 하는 것 보다 좋습니다.for at least one argument, the conversion from Ex to Px is better than the conversion from Ex to Qx.

이 평가를 수행할 때 Mp 또는 Mq이 확장 된 형식으로 적용 될 경우 Px 또는 Qx은 매개 변수 목록에서 확장 된 형식의 매개 변수를 참조 합니다.When performing this evaluation, if Mp or Mq is applicable in its expanded form, then Px or Qx refers to a parameter in the expanded form of the parameter list.

매개 변수 형식 시퀀스 @ no__t-0과 {Q1, Q2, ..., Qn}이 동일 하면 (즉, 각 Pi에 해당 하는 Qi으로의 id 변환이 있는 경우) 다음과 같은 연결 규칙을 순서 대로 적용 하 여 더 나은 함수 멤버를 확인 합니다.In case the parameter type sequences {P1, P2, ..., Pn} and {Q1, Q2, ..., Qn} are equivalent (i.e. each Pi has an identity conversion to the corresponding Qi), the following tie-breaking rules are applied, in order, to determine the better function member.

  • @No__t-0이 제네릭이 아닌 메서드이 고 Mq이 제네릭 메서드인 경우 MpMq 보다 좋습니다.If Mp is a non-generic method and Mq is a generic method, then Mp is better than Mq.
  • 그렇지 않고 Mp이 일반 형식으로 적용 되 고 Mqparams 배열이 며 확장 된 형식에만 적용 될 경우-3 @no__t는 @no__t 보다 좋습니다.Otherwise, if Mp is applicable in its normal form and Mq has a params array and is applicable only in its expanded form, then Mp is better than Mq.
  • 그렇지 않고 MpMq 보다 더 많이 선언 된 매개 변수가 있는 경우 MpMq 보다 좋습니다.Otherwise, if Mp has more declared parameters than Mq, then Mp is better than Mq. 두 메서드가 모두 @no__t 배열을 포함 하 고 확장 된 형식에만 적용할 수 있는 경우이 문제가 발생할 수 있습니다.This can occur if both methods have params arrays and are applicable only in their expanded forms.
  • 그렇지 않고 @no__t의 모든 매개 변수에 해당 하는 인수가 있는 경우-1 @no__t에서 하나 이상의 선택적 매개 변수를 대체 해야 하는 경우에는-1 MpMq 보다 좋습니다.Otherwise if all parameters of Mp have a corresponding argument whereas default arguments need to be substituted for at least one optional parameter in Mq then Mp is better than Mq.
  • 그렇지 않고 MpMq 보다 더 구체적인 매개 변수 형식이 있는 경우 MpMq 보다 좋습니다.Otherwise, if Mp has more specific parameter types than Mq, then Mp is better than Mq. @No__t-0 및 {S1, S2, ..., Sn}MpMq의 인스턴스화되지 않은 및 확장 되지 않은 매개 변수 유형을 나타냅니다.Let {R1, R2, ..., Rn} and {S1, S2, ..., Sn} represent the uninstantiated and unexpanded parameter types of Mp and Mq. Mp의 매개 변수 형식은 Mq 보다 구체적입니다. 각 매개 변수에 대해 RxSx 보다 덜 구체적이 지 않으며, 하나 이상의 매개 변수에 대해 RxSx 보다 구체적입니다.Mp's parameter types are more specific than Mq's if, for each parameter, Rx is not less specific than Sx, and, for at least one parameter, Rx is more specific than Sx:
    • 형식 매개 변수는 형식이 아닌 매개 변수 보다 구체적이 낮습니다.A type parameter is less specific than a non-type parameter.
    • 하나 이상의 형식 인수가 보다 구체적이 고 형식 인수가 다른 생성 된 형식 인수 보다 더 구체적 이면 생성 된 형식이 다른 생성 된 형식 (동일한 수의 형식 인수 포함) 보다 구체적입니다.Recursively, a constructed type is more specific than another constructed type (with the same number of type arguments) if at least one type argument is more specific and no type argument is less specific than the corresponding type argument in the other.
    • 첫 번째의 요소 형식이 두 번째의 요소 형식 보다 구체적 이면 배열 형식은 다른 배열 형식 (차원의 수) 보다 구체적입니다.An array type is more specific than another array type (with the same number of dimensions) if the element type of the first is more specific than the element type of the second.
  • 그렇지 않으면 한 멤버가 리프트 되지 않는 연산자이 고 다른 멤버가 리프트 된 연산자 이면 리프트 되지 않는 연산자가 더 좋습니다.Otherwise if one member is a non-lifted operator and the other is a lifted operator, the non-lifted one is better.
  • 그렇지 않은 경우에는 함수 멤버가 더 나은 방법이 아닙니다.Otherwise, neither function member is better.

식에서의 변환 향상Better conversion from expression

@No__t 식에서-1을 형식 T1로 변환 하는 암시적 변환 C1을 형식 E 형식으로 변환 하는 암시적 변환 (-3 @no__t)을 지정 하는 경우 C1C2 보다 더 나은 변환 @no__t t-9는 E0과 정확히 일치 하지 않고 다음 중 하나 이상이 포함 됩니다.Given an implicit conversion C1 that converts from an expression E to a type T1, and an implicit conversion C2 that converts from an expression E to a type T2, C1 is a better conversion than C2 if E does not exactly match T2 and at least one of the following holds:

정확히 일치 하는 식Exactly matching Expression

다음 중 하나에 해당 하는 경우 E과 형식 T이 지정 되 고, ET과 정확히 일치 합니다.Given an expression E and a type T, E exactly matches T if one of the following holds:

  • E의 형식이 S이 고 S에서 T로의 id 변환이 있습니다.E has a type S, and an identity conversion exists from S to T
  • E은 익명 함수 T은 대리자 형식 D 또는 식 트리 형식 Expression<D> 이며 다음 중 하나입니다.E is an anonymous function, T is either a delegate type D or an expression tree type Expression<D> and one of the following holds:
    • 유추 된 반환 형식 @no__t은 D (유추 된 반환 형식)의 매개 변수 목록 컨텍스트에서 E에 대해 존재 하며, X에서 @no__t의 반환 형식으로의 id 변환이 있습니다.An inferred return type X exists for E in the context of the parameter list of D (Inferred return type), and an identity conversion exists from X to the return type of D
    • @No__t-0이 비동기이 아니고-1 @no__t 반환 형식이 Y 또는 E이 비동기이 고 D가 반환 형식 Task<Y> 이며 다음 중 하나에 해당 합니다.Either E is non-async and D has a return type Y or E is async and D has a return type Task<Y>, and one of the following holds:
      • @No__t의 본문은-1 @no__t 정확히 일치 하는 식입니다.The body of E is an expression that exactly matches Y
      • @No__t-0의 본문은 모든 return 문이-1 @no__t 정확히 일치 하는 식을 반환 하는 문 블록입니다.The body of E is a statement block where every return statement returns an expression that exactly matches Y

변환 대상 향상Better conversion target

두 가지 다른 형식 T1T2을 지정 하는 경우 T2에서 T1로의 암시적 변환이 없고 다음 중 하나 이상이 있는 경우 T1T2 보다 더 나은 변환 대상입니다.Given two different types T1 and T2, T1 is a better conversion target than T2 if no implicit conversion from T2 to T1 exists, and at least one of the following holds:

  • @No__t-0에서 T2로의 암시적 변환이 있습니다.An implicit conversion from T1 to T2 exists
  • T1은 대리자 형식 D1 또는 식 트리 형식 Expression<D1>, T2은 대리자 형식 D2 또는 식 트리 형식 Expression<D2>, D1의 반환 형식 S1 이며 다음 중 하나입니다. :T1 is either a delegate type D1 or an expression tree type Expression<D1>, T2 is either a delegate type D2 or an expression tree type Expression<D2>, D1 has a return type S1 and one of the following holds:
    • D2은 void를 반환 합니다.D2 is void returning
    • D2은-1 @no__t 반환 형식이 고, S1S2 보다 더 나은 변환 대상입니다.D2 has a return type S2, and S1 is a better conversion target than S2
  • T1Task<S1>이 고 T2Task<S2> 이며 S1S2 보다 더 나은 변환 대상입니다.T1 is Task<S1>, T2 is Task<S2>, and S1 is a better conversion target than S2
  • T1S1 또는 S1?입니다. 여기서 S1은 부호 있는 정수 형식이 고 T2S2 또는 S2?입니다. 여기서 S2은 부호 없는 정수 계열 형식입니다.T1 is S1 or S1? where S1 is a signed integral type, and T2 is S2 or S2? where S2 is an unsigned integral type. 구체적으로는 다음과 같습니다.Specifically:
    • S1 sbyte 이며 S2byte, ushort, uint 또는 @no__t입니다.S1 is sbyte and S2 is byte, ushort, uint, or ulong
    • short @no__t이 고 S2ushort, uint 또는 ulong입니다.S1 is short and S2 is ushort, uint, or ulong
    • int @no__t이 고 S2uint 또는 ulong입니다.S1 is int and S2 is uint, or ulong
    • S1long 이며 S2ulong입니다.S1 is long and S2 is ulong

제네릭 클래스에서 오버 로드Overloading in generic classes

선언 된 서명이 고유 해야 하지만 형식 인수를 대체 하면 시그니처가 동일할 수 있습니다.While signatures as declared must be unique, it is possible that substitution of type arguments results in identical signatures. 이러한 경우 위의 오버 로드 확인 규칙은 가장 구체적인 멤버를 선택 합니다.In such cases, the tie-breaking rules of overload resolution above will pick the most specific member.

다음 예에서는이 규칙에 따라 유효 하 고 유효 하지 않은 오버 로드를 보여 줍니다.The following examples show overloads that are valid and invalid according to this rule:

interface I1<T> {...}

interface I2<T> {...}

class G1<U>
{
    int F1(U u);                  // Overload resolution for G<int>.F1
    int F1(int i);                // will pick non-generic

    void F2(I1<U> a);             // Valid overload
    void F2(I2<U> a);
}

class G2<U,V>
{
    void F3(U u, V v);            // Valid, but overload resolution for
    void F3(V v, U u);            // G2<int,int>.F3 will fail

    void F4(U u, I1<V> v);        // Valid, but overload resolution for    
    void F4(I1<V> v, U u);        // G2<I1<int>,int>.F4 will fail

    void F5(U u1, I1<V> v2);      // Valid overload
    void F5(V v1, U u2);

    void F6(ref U u);             // valid overload
    void F6(out V v);
}

동적 오버 로드 확인의 컴파일 타임 검사Compile-time checking of dynamic overload resolution

동적으로 바인딩된 대부분의 작업의 경우 가능한 해결 방법 집합은 컴파일 시간에 알 수 없습니다.For most dynamically bound operations the set of possible candidates for resolution is unknown at compile-time. 그러나 경우에 따라 후보 집합은 컴파일 시간에 알려집니다.In certain cases, however the candidate set is known at compile-time:

  • 동적 인수를 사용 하는 정적 메서드 호출Static method calls with dynamic arguments
  • 수신자가 동적 식이 아닌 인스턴스 메서드 호출Instance method calls where the receiver is not a dynamic expression
  • 수신자가 동적 식이 아닌 인덱서 호출Indexer calls where the receiver is not a dynamic expression
  • 동적 인수를 사용 하는 생성자 호출Constructor calls with dynamic arguments

이러한 경우 런타임에 적용 될 수 있는 것이 있는지 확인 하기 위해 각 후보에 대해 제한 된 컴파일 시간 검사를 수행 합니다. 이 검사는 다음 단계로 구성 됩니다.In these cases a limited compile-time check is performed for each candidate to see if any of them could possibly apply at run-time.This check consists of the following steps:

  • 부분 형식 유추: @No__t-0 형식의 인수에서 직접 또는 간접적으로 종속 되지 않는 모든 형식 인수는 형식 유추의 규칙을 사용 하 여 유추 됩니다.Partial type inference: Any type argument that does not depend directly or indirectly on an argument of type dynamic is inferred using the rules of Type inference. 나머지 형식 인수를 알 수 없습니다.The remaining type arguments are unknown.
  • 부분 적용 가능성 검사: 적용 가능 함수 멤버에 따라 적용 가능성을 확인 하지만 해당 형식을 알 수 없는 매개 변수는 무시 합니다.Partial applicability check: Applicability is checked according to Applicable function member, but ignoring parameters whose types are unknown.
  • 이 테스트를 통과 하는 후보가 없으면 컴파일 시간 오류가 발생 합니다.If no candidate passes this test, a compile-time error occurs.

함수 멤버 호출Function member invocation

이 섹션에서는 런타임에 특정 함수 멤버를 호출 하는 프로세스에 대해 설명 합니다.This section describes the process that takes place at run-time to invoke a particular function member. 바인딩 시간 프로세스는 일련의 후보 함수 멤버에 오버 로드 확인을 적용 하 여 호출할 특정 멤버를 이미 결정 했다고 가정 합니다.It is assumed that a binding-time process has already determined the particular member to invoke, possibly by applying overload resolution to a set of candidate function members.

호출 프로세스를 설명 하기 위해 함수 멤버는 다음 두 가지 범주로 구분 됩니다.For purposes of describing the invocation process, function members are divided into two categories:

  • 정적 함수 멤버입니다.Static function members. 인스턴스 생성자, 정적 메서드, 정적 속성 접근자 및 사용자 정의 연산자가 있습니다.These are instance constructors, static methods, static property accessors, and user-defined operators. 정적 함수 멤버는 항상 비가상입니다.Static function members are always non-virtual.
  • 인스턴스 함수 멤버.Instance function members. 인스턴스 메서드, 인스턴스 속성 접근자 및 인덱서 접근자가 있습니다.These are instance methods, instance property accessors, and indexer accessors. 인스턴스 함수 멤버는 비가상 또는 virtual 이며 항상 특정 인스턴스에서 호출 됩니다.Instance function members are either non-virtual or virtual, and are always invoked on a particular instance. 인스턴스는 인스턴스 식으로 계산 되 고 함수 멤버 내에서 this (이 액세스)으로 액세스할 수 있게 됩니다.The instance is computed by an instance expression, and it becomes accessible within the function member as this (This access).

함수 멤버 호출의 런타임 처리는 다음 단계로 구성 됩니다. 여기서 M은 함수 멤버이 고 M이 인스턴스 멤버인 경우-2 @no__t는 인스턴스 식입니다.The run-time processing of a function member invocation consists of the following steps, where M is the function member and, if M is an instance member, E is the instance expression:

  • @No__t-0 이면 정적 함수 멤버입니다.If M is a static function member:

    • 인수 목록은 인수목록에 설명 된 대로 평가 됩니다.The argument list is evaluated as described in Argument lists.
    • M이 호출 됩니다.M is invoked.
  • @No__t-0은 value_type에서 선언 된 인스턴스 함수 멤버입니다.If M is an instance function member declared in a value_type:

    • E이 계산 됩니다.E is evaluated. 이 평가에서 예외가 발생 하면 추가 단계가 실행 되지 않습니다.If this evaluation causes an exception, then no further steps are executed.
    • @No__t-0이 변수로 분류 되지 않으면 E 형식의 임시 지역 변수가 만들어지고 E의 값이 해당 변수에 할당 됩니다.If E is not classified as a variable, then a temporary local variable of E's type is created and the value of E is assigned to that variable. 그런 다음 E은 해당 임시 지역 변수에 대 한 참조로 다시 분류할 됩니다.E is then reclassified as a reference to that temporary local variable. 임시 변수는 M 내에서 this으로 액세스할 수 있지만 다른 방식으로는 액세스할 수 없습니다.The temporary variable is accessible as this within M, but not in any other way. 따라서 E이 true 변수인 경우에만 호출자가-1이 this에 @no__t 변경 내용을 관찰할 수 있습니다.Thus, only when E is a true variable is it possible for the caller to observe the changes that M makes to this.
    • 인수 목록은 인수목록에 설명 된 대로 평가 됩니다.The argument list is evaluated as described in Argument lists.
    • M이 호출 됩니다.M is invoked. @No__t-0에서 참조 하는 변수는 this에서 참조 하는 변수가 됩니다.The variable referenced by E becomes the variable referenced by this.
  • @No__t-0은 reference_type에서 선언 된 인스턴스 함수 멤버입니다.If M is an instance function member declared in a reference_type:

    • E이 계산 됩니다.E is evaluated. 이 평가에서 예외가 발생 하면 추가 단계가 실행 되지 않습니다.If this evaluation causes an exception, then no further steps are executed.
    • 인수 목록은 인수목록에 설명 된 대로 평가 됩니다.The argument list is evaluated as described in Argument lists.
    • @No__t의 형식이 value_type인 경우 E을 형식 object로 변환 하기 위해 boxing 변환 (boxing변환)이 수행 되 고 E는 다음 단계에서 object 형식으로 간주 됩니다.If the type of E is a value_type, a boxing conversion (Boxing conversions) is performed to convert E to type object, and E is considered to be of type object in the following steps. 이 경우 MSystem.Object의 멤버일 수만 있습니다.In this case, M could only be a member of System.Object.
    • @No__t-0의 값이 유효한 지 확인 합니다.The value of E is checked to be valid. @No__t-0의 값이-1 @no__t 이면 System.NullReferenceException가 throw 되며 추가 단계가 실행 되지 않습니다.If the value of E is null, a System.NullReferenceException is thrown and no further steps are executed.
    • 호출할 함수 멤버 구현이 결정 됩니다.The function member implementation to invoke is determined:
      • @No__t-0의 바인딩 시간 형식이 인터페이스인 경우 호출할 함수 멤버는 E에서 참조 하는 인스턴스의 런타임 형식에서 제공 하는 M의 구현입니다.If the binding-time type of E is an interface, the function member to invoke is the implementation of M provided by the run-time type of the instance referenced by E. 이 함수 멤버는 인터페이스 매핑 규칙 (인터페이스 매핑)을 적용 하 여 E에서 참조 하는 인스턴스의 런타임 형식에서 제공 하는 @no__t 1의 구현을 확인 하는 방법으로 결정 됩니다.This function member is determined by applying the interface mapping rules (Interface mapping) to determine the implementation of M provided by the run-time type of the instance referenced by E.
      • 그렇지 않고 M이 가상 함수 멤버 이면 호출할 함수 멤버는 E에서 참조 하는 인스턴스의 런타임 형식에서 제공 하는 M의 구현입니다.Otherwise, if M is a virtual function member, the function member to invoke is the implementation of M provided by the run-time type of the instance referenced by E. 이 함수 멤버는 E에서 참조 하는 인스턴스의 런타임 형식과 관련 하 여 M의 가장 많이 파생 된 구현 (가상 메서드)을 결정 하는 규칙을 적용 하 여 결정 됩니다.This function member is determined by applying the rules for determining the most derived implementation (Virtual methods) of M with respect to the run-time type of the instance referenced by E.
      • 그렇지 않으면 M은 비가상 함수 멤버이 고 호출할 함수 멤버는 M입니다.Otherwise, M is a non-virtual function member, and the function member to invoke is M itself.
    • 위의 단계에서 결정 된 함수 멤버 구현이 호출 됩니다.The function member implementation determined in the step above is invoked. @No__t-0에서 참조 하는 개체는 this에서 참조 하는 개체가 됩니다.The object referenced by E becomes the object referenced by this.

Boxed 인스턴스에 대 한 호출Invocations on boxed instances

Value_type 에 구현 된 함수 멤버는 다음과 같은 경우 value_type 의 boxed 인스턴스를 통해 호출할 수 있습니다.A function member implemented in a value_type can be invoked through a boxed instance of that value_type in the following situations:

  • 함수 멤버가 object 형식에서 상속 된 메서드의 @no__t 0이 고 object 형식의 인스턴스 식을 통해 호출 되는 경우When the function member is an override of a method inherited from type object and is invoked through an instance expression of type object.
  • 함수 멤버가 인터페이스 함수 멤버의 구현이 고 interface_type의 인스턴스 식을 통해 호출 되는 경우When the function member is an implementation of an interface function member and is invoked through an instance expression of an interface_type.
  • 대리자를 통해 함수 멤버를 호출 하는 경우When the function member is invoked through a delegate.

이러한 상황에서 boxed 인스턴스는 value_type의 변수를 포함 하는 것으로 간주 되 고이 변수는 함수 멤버 호출 내의 this에서 참조 하는 변수가 됩니다.In these situations, the boxed instance is considered to contain a variable of the value_type, and this variable becomes the variable referenced by this within the function member invocation. 특히이는 함수 멤버가 boxed 인스턴스에서 호출 될 때 함수 멤버가 boxed 인스턴스에 포함 된 값을 수정할 수 있음을 의미 합니다.In particular, this means that when a function member is invoked on a boxed instance, it is possible for the function member to modify the value contained in the boxed instance.

기본 식Primary expressions

기본 식에는 가장 간단한 형태의 식이 포함 됩니다.Primary expressions include the simplest forms of expressions.

primary_expression
    : primary_no_array_creation_expression
    | array_creation_expression
    ;

primary_no_array_creation_expression
    : literal
    | interpolated_string_expression
    | simple_name
    | parenthesized_expression
    | member_access
    | invocation_expression
    | element_access
    | this_access
    | base_access
    | post_increment_expression
    | post_decrement_expression
    | object_creation_expression
    | delegate_creation_expression
    | anonymous_object_creation_expression
    | typeof_expression
    | checked_expression
    | unchecked_expression
    | default_value_expression
    | nameof_expression
    | anonymous_method_expression
    | primary_no_array_creation_expression_unsafe
    ;

주 식은 array_creation_expressions와 primary_no_array_creation_expressions 간에 구분 됩니다.Primary expressions are divided between array_creation_expressions and primary_no_array_creation_expressions. 배열 생성 식을 다른 간단한 식 형식과 함께 나열 하는 대신 이러한 식으로 처리 하면 문법을 통해 다음과 같은 잠재적으로 혼동 될 수 있습니다.Treating array-creation-expression in this way, rather than listing it along with the other simple expression forms, enables the grammar to disallow potentially confusing code such as

object o = new int[3][1];

그렇지 않으면 다음과 같이 해석 됩니다.which would otherwise be interpreted as

object o = (new int[3])[1];

리터럴Literals

리터럴 (리터럴)으로 구성 된 primary_expression 는 값으로 분류 됩니다.A primary_expression that consists of a literal (Literals) is classified as a value.

보간된 문자열Interpolated strings

Interpolated_string_expression{}으로 구분 되는 구멍이 포함 된 $ 부호와, 식 및 형식 지정 사양으로 구성 됩니다.An interpolated_string_expression consists of a $ sign followed by a regular or verbatim string literal, wherein holes, delimited by { and }, enclose expressions and formatting specifications. 보간된 문자열 식은 보간된 문자열 리터럴에설명 된 대로 개별 토큰으로 분할 된 interpolated_string_literal 의 결과입니다.An interpolated string expression is the result of an interpolated_string_literal that has been broken up into individual tokens, as described in Interpolated string literals.

interpolated_string_expression
    : '$' interpolated_regular_string
    | '$' interpolated_verbatim_string
    ;

interpolated_regular_string
    : interpolated_regular_string_whole
    | interpolated_regular_string_start interpolated_regular_string_body interpolated_regular_string_end
    ;

interpolated_regular_string_body
    : interpolation (interpolated_regular_string_mid interpolation)*
    ;

interpolation
    : expression
    | expression ',' constant_expression
    ;

interpolated_verbatim_string
    : interpolated_verbatim_string_whole
    | interpolated_verbatim_string_start interpolated_verbatim_string_body interpolated_verbatim_string_end
    ;

interpolated_verbatim_string_body
    : interpolation (interpolated_verbatim_string_mid interpolation)+
    ;

보간의 constant_expressionint로의 암시적 변환이 있어야 합니다.The constant_expression in an interpolation must have an implicit conversion to int.

Interpolated_string_expression 는 값으로 분류 됩니다.An interpolated_string_expression is classified as a value. 암시적으로 보간된 문자열 변환 (암시적으로 보간된 문자열변환)을 사용 하 여 System.IFormattable 또는 System.FormattableString로 즉시 변환 되는 경우 보간된 문자열 식에 해당 형식이 있습니다.If it is immediately converted to System.IFormattable or System.FormattableString with an implicit interpolated string conversion (Implicit interpolated string conversions), the interpolated string expression has that type. 그렇지 않으면 string 형식입니다.Otherwise, it has the type string.

보간된 문자열의 형식이 0 @no__t 또는 System.FormattableString 이면 의미는 System.Runtime.CompilerServices.FormattableStringFactory.Create에 대 한 호출입니다.If the type of an interpolated string is System.IFormattable or System.FormattableString, the meaning is a call to System.Runtime.CompilerServices.FormattableStringFactory.Create. 형식이 string 인 경우 식의 의미는 string.Format에 대 한 호출입니다.If the type is string, the meaning of the expression is a call to string.Format. 두 경우 모두 호출의 인수 목록은 각 보간에 대 한 자리 표시자와 자리 표시자에 해당 하는 각 식에 대 한 인수를 포함 하는 형식 문자열 리터럴로 구성 됩니다.In both cases, the argument list of the call consists of a format string literal with placeholders for each interpolation, and an argument for each expression corresponding to the place holders.

형식 문자열 리터럴은 다음과 같이 생성 됩니다. 여기서 Ninterpolated_string_expression의 보간 수입니다.The format string literal is constructed as follows, where N is the number of interpolations in the interpolated_string_expression:

  • Interpolated_regular_string_whole 또는 interpolated_verbatim_string_whole 가 @no__t 2 기호를 따르는 경우 형식 문자열 리터럴은 해당 토큰입니다.If an interpolated_regular_string_whole or an interpolated_verbatim_string_whole follows the $ sign, then the format string literal is that token.
  • 그렇지 않으면 형식 문자열 리터럴은 다음과 같이 구성 됩니다.Otherwise, the format string literal consists of:
    • 첫 번째 interpolated_regular_string_start 또는 interpolated_verbatim_string_startFirst the interpolated_regular_string_start or interpolated_verbatim_string_start
    • 그런 다음 각 숫자에 대해-0 0에서 N-1로 @no__t 합니다.Then for each number I from 0 to N-1:
      • @No__t의 10 진수 표현입니다.The decimal representation of I
      • 그런 다음 해당 보간constant_expression이 있는 경우 , (쉼표)와 constant_expression 값의 10 진수 표현이 차례로 표시 됩니다.Then, if the corresponding interpolation has a constant_expression, a , (comma) followed by the decimal representation of the value of the constant_expression
      • 그런 다음 interpolated_regular_string_mid, interpolated_regular_string_end, interpolated_verbatim_string_mid 또는 interpolated_verbatim_string_end 바로 다음에 해당 하는 보간을 바로 뒤에 있습니다.Then the interpolated_regular_string_mid, interpolated_regular_string_end, interpolated_verbatim_string_mid or interpolated_verbatim_string_end immediately following the corresponding interpolation.

후속 인수는 단순히 보간 (있는 경우)의 입니다.The subsequent arguments are simply the expressions from the interpolations (if any), in order.

TODO: 예제입니다.TODO: examples.

단순 이름Simple names

Simple_name 는 식별자로 구성 되며, 선택적으로 다음에 형식 인수 목록이 옵니다.A simple_name consists of an identifier, optionally followed by a type argument list:

simple_name
    : identifier type_argument_list?
    ;

Simple_nameI 또는 @no__t 형식 중 하나입니다. 여기서 I은 단일 식별자이 고 <A1,...,Ak>는 선택적 type_argument_list입니다.A simple_name is either of the form I or of the form I<A1,...,Ak>, where I is a single identifier and <A1,...,Ak> is an optional type_argument_list. Type_argument_list 가 지정 되지 않은 경우-1을 0으로 @no__t 고려 하십시오.When no type_argument_list is specified, consider K to be zero. Simple_name 평가 되 고 다음과 같이 분류 됩니다.The simple_name is evaluated and classified as follows:

  • @No__t-0이 0이 고 블록 내에 simple_name 표시 되 고 블록의 (또는 바깥쪽 블록의) 지역 변수 선언 공간 (선언)에 지역 변수, 매개 변수 또는 상수가 포함 된 경우 name @ no__t-6 인 경우 simple_name 는 해당 지역 변수, 매개 변수 또는 상수를 참조 하 고 변수 또는 값으로 분류 됩니다.If K is zero and the simple_name appears within a block and if the block's (or an enclosing block's) local variable declaration space (Declarations) contains a local variable, parameter or constant with name I, then the simple_name refers to that local variable, parameter or constant and is classified as a variable or value.

  • @No__t-0이 0이 고 simple_name 이 제네릭 메서드 선언의 본문 내에 표시 되 고 해당 선언에 이름이 @ no__t-2 인 형식 매개 변수가 포함 된 경우 simple_name 는 해당 형식 매개 변수를 참조 합니다.If K is zero and the simple_name appears within the body of a generic method declaration and if that declaration includes a type parameter with name I, then the simple_name refers to that type parameter.

  • 그 외의 경우에는 각 인스턴스 (인스턴스 유형)에 대해 즉시 바깥쪽 형식 선언의 인스턴스 형식으로 시작 하 고 각 바깥쪽 클래스 또는 구조체 선언 (있는 경우)의 인스턴스 형식으로 계속 하 여 no__t을 입력 합니다.Otherwise, for each instance type T (The instance type), starting with the instance type of the immediately enclosing type declaration and continuing with the instance type of each enclosing class or struct declaration (if any):

    • @No__t-0이 0이 고 T의 선언에 name @ no__t-2 인 형식 매개 변수가 포함 된 경우 simple_name 는 해당 형식 매개 변수를 참조 합니다.If K is zero and the declaration of T includes a type parameter with name I, then the simple_name refers to that type parameter.
    • 그렇지 않고 K @ no__t-4type 인수를 사용 하는 T에서 I의 멤버 조회 (멤버 조회)가 일치 하는 경우 일치 하는 항목이 생성 됩니다.Otherwise, if a member lookup (Member lookup) of I in T with K type arguments produces a match:
      • @No__t-0이 즉시 바깥쪽 클래스 또는 구조체 형식의 인스턴스 형식이 고 조회에서 하나 이상의 메서드를 식별 하는 경우에는 연결 된 인스턴스 식이 this 인 메서드 그룹이 반환 됩니다.If T is the instance type of the immediately enclosing class or struct type and the lookup identifies one or more methods, the result is a method group with an associated instance expression of this. 형식 인수 목록을 지정 하는 경우 제네릭 메서드 (메서드 호출)를 호출 하는 데 사용 됩니다.If a type argument list was specified, it is used in calling a generic method (Method invocations).
      • 그렇지 않고 T이 즉시 바깥쪽 클래스 또는 구조체 형식의 인스턴스 형식이 면 조회에서 인스턴스 멤버를 식별 하 고, 참조가 인스턴스 생성자, 인스턴스 메서드 또는 인스턴스 접근자의 본문 내에서 발생 하는 경우 결과는 는 this.I 형식의 멤버 액세스 (멤버 액세스)와 동일 합니다.Otherwise, if T is the instance type of the immediately enclosing class or struct type, if the lookup identifies an instance member, and if the reference occurs within the body of an instance constructor, an instance method, or an instance accessor, the result is the same as a member access (Member access) of the form this.I. 이는 K이 0 인 경우에만 발생할 수 있습니다.This can only happen when K is zero.
      • 그렇지 않으면 결과는 T.I 또는 T.I<A1,...,Ak> 형식의 멤버 액세스 (멤버 액세스)와 동일 합니다.Otherwise, the result is the same as a member access (Member access) of the form T.I or T.I<A1,...,Ak>. 이 경우 simple_name 는 인스턴스 멤버를 참조 하는 바인딩 시간 오류입니다.In this case, it is a binding-time error for the simple_name to refer to an instance member.
  • 각 네임 스페이스 @ no__t-0에 대해 simple_name 가 발생 하는 네임 스페이스부터 시작 하 여 각 바깥쪽 네임 스페이스 (있는 경우)를 계속 하 고 전역 네임 스페이스로 종료 하는 경우 엔터티를 찾을 때까지 다음 단계를 평가 합니다.Otherwise, for each namespace N, starting with the namespace in which the simple_name occurs, continuing with each enclosing namespace (if any), and ending with the global namespace, the following steps are evaluated until an entity is located:

    • @No__t-0이 0이 고 I이 @ no__t에서 네임 스페이스의 이름인 경우는 다음과 같습니다.If K is zero and I is the name of a namespace in N, then:
      • Simple_name 발생 하는 위치가 N에 대 한 네임 스페이스 선언으로 묶여 있고 네임 스페이스 선언에 @ no__t-4를와 연결 하는 extern_alias_directive 또는 using_alias_directive 가 포함 된 경우 네임 스페이스 또는 형식, simple_name 는 모호 하며 컴파일 타임 오류가 발생 합니다.If the location where the simple_name occurs is enclosed by a namespace declaration for N and the namespace declaration contains an extern_alias_directive or using_alias_directive that associates the name I with a namespace or type, then the simple_name is ambiguous and a compile-time error occurs.
      • 그렇지 않으면 simple_nameN에서 I 이라는 네임 스페이스를 참조 합니다.Otherwise, the simple_name refers to the namespace named I in N.
    • 그렇지 않고 N에 이름 @ no__t-1과 K @ no__t 형식 매개 변수가 있는 액세스 가능 형식이 포함 된 경우:Otherwise, if N contains an accessible type having name I and K type parameters, then:
      • @No__t-0이 0이 고 simple_name 발생 하는 위치가 N에 대 한 네임 스페이스 선언으로 묶여 있고 네임 스페이스 선언에 이름 @ no__t-5는 네임 스페이스 또는 형식으로, simple_name 는 모호 하며 컴파일 타임 오류가 발생 합니다.If K is zero and the location where the simple_name occurs is enclosed by a namespace declaration for N and the namespace declaration contains an extern_alias_directive or using_alias_directive that associates the name I with a namespace or type, then the simple_name is ambiguous and a compile-time error occurs.
      • 그렇지 않으면 namespace_or_type_name 는 지정 된 형식 인수를 사용 하 여 생성 된 형식을 참조 합니다.Otherwise, the namespace_or_type_name refers to the type constructed with the given type arguments.
    • 그렇지 않고 simple_name 발생 하는 위치가 @ no__t-1에 대 한 네임 스페이스 선언으로 묶여 있는 경우:Otherwise, if the location where the simple_name occurs is enclosed by a namespace declaration for N:
      • @No__t-0이 0이 고 네임 스페이스 선언에 @ no__t-3 이름을 가져온 네임 스페이스 또는 형식과 연결 하는 extern_alias_directive 또는 using_alias_directive 가 포함 된 경우 simple_name 는 해당 네임 스페이스를 참조 합니다. 입력할.If K is zero and the namespace declaration contains an extern_alias_directive or using_alias_directive that associates the name I with an imported namespace or type, then the simple_name refers to that namespace or type.
      • 그렇지 않고 네임 스페이스 선언의 using_namespace_directives 및 using_static_directives에서 가져온 네임 스페이스 및 형식 선언에 정확히 하나의 액세스 가능 형식 또는 이름이 @ no__ 인 확장명이 없는 정적 멤버가 포함 된 경우 t-2 및 K @ no__t-4type 매개 변수를 사용 하는 경우 simple_name 는 지정 된 형식 인수를 사용 하 여 생성 된 해당 형식 또는 멤버를 참조 합니다.Otherwise, if the namespaces and type declarations imported by the using_namespace_directives and using_static_directives of the namespace declaration contain exactly one accessible type or non-extension static member having name I and K type parameters, then the simple_name refers to that type or member constructed with the given type arguments.
      • 그렇지 않고 네임 스페이스 선언의 using_namespace_directives에서 가져온 네임 스페이스 및 형식에 두 개 이상의 액세스 가능한 형식 또는 이름 @ no__t-1과 K @ no__t 형식 매개 변수가 포함 된 확장 메서드 정적 멤버가 포함 된 경우 그런 다음 simple_name 는 모호 하 고 오류가 발생 합니다.Otherwise, if the namespaces and types imported by the using_namespace_directives of the namespace declaration contain more than one accessible type or non-extension-method static member having name I and K type parameters, then the simple_name is ambiguous and an error occurs.

    이 전체 단계는 namespace_or_type_name (네임 스페이스 및 형식 이름) 처리의 해당 단계와 정확히 나란히 있습니다.Note that this entire step is exactly parallel to the corresponding step in the processing of a namespace_or_type_name (Namespace and type names).

  • 그렇지 않으면 simple_name 이 정의 되지 않고 컴파일 타임 오류가 발생 합니다.Otherwise, the simple_name is undefined and a compile-time error occurs.

괄호로 묶은 식Parenthesized expressions

Parenthesized_expression 은 괄호로 묶인 으로 구성 됩니다.A parenthesized_expression consists of an expression enclosed in parentheses.

parenthesized_expression
    : '(' expression ')'
    ;

괄호 안의 식을 계산 하 여 parenthesized_expression 를 평가 합니다.A parenthesized_expression is evaluated by evaluating the expression within the parentheses. 괄호 안의 식이 네임 스페이스나 형식을 나타내는 경우 컴파일 타임 오류가 발생 합니다.If the expression within the parentheses denotes a namespace or type, a compile-time error occurs. 그렇지 않으면 parenthesized_expression 의 결과는 포함 된 의 평가 결과입니다.Otherwise, the result of the parenthesized_expression is the result of the evaluation of the contained expression.

멤버 액세스Member access

Member_accessprimary_expression, predefined_type또는 qualified_alias_member으로 구성 되 고, 그 뒤에는 "." 토큰이 오고, 그 뒤에 식별자가 오고, 선택적으로 그 뒤에 type_argument_list가 나옵니다.A member_access consists of a primary_expression, a predefined_type, or a qualified_alias_member, followed by a "." token, followed by an identifier, optionally followed by a type_argument_list.

member_access
    : primary_expression '.' identifier type_argument_list?
    | predefined_type '.' identifier type_argument_list?
    | qualified_alias_member '.' identifier
    ;

predefined_type
    : 'bool'   | 'byte'  | 'char'  | 'decimal' | 'double' | 'float' | 'int' | 'long'
    | 'object' | 'sbyte' | 'short' | 'string'  | 'uint'   | 'ulong' | 'ushort'
    ;

Qualified_alias_member Production는 네임 스페이스 별칭 한정자에 정의 되어 있습니다.The qualified_alias_member production is defined in Namespace alias qualifiers.

Member_accessE.I 또는 @no__t 형식의 형식 중 하나입니다. 여기서 E은 기본 식이 고, I는 단일 식별자 이며, <A1, ..., Ak>는 선택적 type_argument_list입니다.A member_access is either of the form E.I or of the form E.I<A1, ..., Ak>, where E is a primary-expression, I is a single identifier and <A1, ..., Ak> is an optional type_argument_list. Type_argument_list 가 지정 되지 않은 경우-1을 0으로 @no__t 고려 하십시오.When no type_argument_list is specified, consider K to be zero.

Member_access 형식이 dynamicprimary_expression 는 동적으로 바인딩됩니다 (동적 바인딩).A member_access with a primary_expression of type dynamic is dynamically bound (Dynamic binding). 이 경우 컴파일러는 멤버 액세스를 dynamic 형식의 속성 액세스로 분류 합니다.In this case the compiler classifies the member access as a property access of type dynamic. 그런 다음 member_access 의 의미를 결정 하는 규칙은 런타임에 primary_expression의 컴파일 시간 형식 대신 런타임 형식을 사용 하 여 적용 됩니다.The rules below to determine the meaning of the member_access are then applied at run-time, using the run-time type instead of the compile-time type of the primary_expression. 이 런타임 분류가 메서드 그룹으로 이어지는 경우 멤버 액세스는 invocation_expressionprimary_expression 이어야 합니다.If this run-time classification leads to a method group, then the member access must be the primary_expression of an invocation_expression.

Member_access 평가 되 고 다음과 같이 분류 됩니다.The member_access is evaluated and classified as follows:

  • @No__t-0이 0이 고 E이 네임 스페이스이 고 E에 이름이 @ no__t-3 인 중첩 된 네임 스페이스가 포함 된 경우 그 결과는 해당 네임 스페이스입니다.If K is zero and E is a namespace and E contains a nested namespace with name I, then the result is that namespace.
  • @No__t-0이 네임 스페이스이 고 E에 name @ no__t 및 K @ no__t 매개 변수가 있는 액세스 가능 형식이 포함 된 경우, 결과는 지정 된 형식 인수를 사용 하 여 생성 된 형식입니다.Otherwise, if E is a namespace and E contains an accessible type having name I and K type parameters, then the result is that type constructed with the given type arguments.
  • @No__t-0이 형식으로 분류 된 predefined_type 이거나 primary_expression 인 경우 E이 형식 매개 변수가 아니고 K @ no__t-8type 매개 변수를 사용 하 여 E의 멤버 조회 (멤버 조회@no__t) 인 경우 일치 하는 항목이 생성 됩니다. 그런 다음 E.I가 평가 되 고 다음과 같이 분류 됩니다.If E is a predefined_type or a primary_expression classified as a type, if E is not a type parameter, and if a member lookup (Member lookup) of I in E with K type parameters produces a match, then E.I is evaluated and classified as follows:
    • @No__t-0은 형식을 식별 하는 경우 지정 된 형식 인수를 사용 하 여 생성 된 형식입니다.If I identifies a type, then the result is that type constructed with the given type arguments.
    • @No__t-0에서 하나 이상의 메서드를 식별 하는 경우 결과는 연결 된 인스턴스 식이 없는 메서드 그룹입니다.If I identifies one or more methods, then the result is a method group with no associated instance expression. 형식 인수 목록을 지정 하는 경우 제네릭 메서드 (메서드 호출)를 호출 하는 데 사용 됩니다.If a type argument list was specified, it is used in calling a generic method (Method invocations).
    • @No__t-0이 static 속성을 식별 하는 경우에는 연결 된 인스턴스 식이 없는 속성 액세스 결과가 반환 됩니다.If I identifies a static property, then the result is a property access with no associated instance expression.
    • @No__t-0 static 필드를 식별 합니다.If I identifies a static field:
      • 필드가-0 @no__t이 고 필드가 선언 된 클래스 또는 구조체의 정적 생성자 외부에서 참조가 발생 하는 경우 결과는 값, 즉 @ no__t-2에 있는 정적 필드 @ no__t-1의 값입니다.If the field is readonly and the reference occurs outside the static constructor of the class or struct in which the field is declared, then the result is a value, namely the value of the static field I in E.
      • 그렇지 않으면 결과는 변수가 됩니다. 즉, @ no__t-1의 정적 필드 @ no__t-0입니다.Otherwise, the result is a variable, namely the static field I in E.
    • @No__t-0 인 경우 static 이벤트를 식별 합니다.If I identifies a static event:
      • 이벤트가 선언 된 클래스 또는 구조체 내에서 참조가 발생 하 고 이벤트가 event_accessor_declarations (이벤트) 없이 선언 된 경우 @no__t, I이 정적 필드인 것 처럼 정확 하 게 처리 됩니다.If the reference occurs within the class or struct in which the event is declared, and the event was declared without event_accessor_declarations (Events), then E.I is processed exactly as if I were a static field.
      • 그렇지 않으면 연결 된 인스턴스 식이 없는 이벤트 액세스가 발생 합니다.Otherwise, the result is an event access with no associated instance expression.
    • @No__t-0이 상수를 식별 하는 경우 결과는 값, 즉 해당 상수의 값입니다.If I identifies a constant, then the result is a value, namely the value of that constant.
    • @No__t-0에서 열거형 멤버를 식별 하는 경우 결과는 값, 즉 해당 열거형 멤버의 값입니다.If I identifies an enumeration member, then the result is a value, namely the value of that enumeration member.
    • 그렇지 않으면 E.I은 잘못 된 멤버 참조 이며 컴파일 시간 오류가 발생 합니다.Otherwise, E.I is an invalid member reference, and a compile-time error occurs.
  • @No__t-0이 속성 액세스, 인덱서 액세스, 변수 또는 값 인 경우 @ no__t-1 인 형식 및 K @ no__t-6type 인수를 사용 하는 T에서 I의 멤버 조회 (멤버 조회)는 일치 하는 항목을 생성 한 다음 E.I이 평가 됩니다. 다음과 같이 분류 됩니다.If E is a property access, indexer access, variable, or value, the type of which is T, and a member lookup (Member lookup) of I in T with K type arguments produces a match, then E.I is evaluated and classified as follows:
    • 첫째, E이 속성 또는 인덱서 액세스 인 경우 속성 또는 인덱서 액세스의 값 (식의 값)을 가져오고 E를 값으로 다시 분류할.First, if E is a property or indexer access, then the value of the property or indexer access is obtained (Values of expressions) and E is reclassified as a value.
    • @No__t-0에서 하나 이상의 메서드를 식별 하는 경우에는 연결 된 인스턴스 식이 E 인 메서드 그룹이 반환 됩니다.If I identifies one or more methods, then the result is a method group with an associated instance expression of E. 형식 인수 목록을 지정 하는 경우 제네릭 메서드 (메서드 호출)를 호출 하는 데 사용 됩니다.If a type argument list was specified, it is used in calling a generic method (Method invocations).
    • @No__t-0은 인스턴스 속성을 식별 하 고,If I identifies an instance property,
      • @No__t-0이 this 인 경우 I는 setter 없이 자동으로 구현 된 속성 (자동으로 구현 된 속성)을 식별 하 고, 참조는 클래스 또는 구조체 형식에 대 한 인스턴스 생성자 내에서-4를 @no__t 합니다. 는 변수 이며, this로 제공 되는 @no__t의 인스턴스에서 I로 제공 되는 자동 속성의 숨겨진 지원 필드입니다.If E is this, I identifies an automatically implemented property (Automatically implemented properties) without a setter, and the reference occurs within an instance constructor for a class or struct type T, then the result is a variable, namely the hidden backing field for the auto-property given by I in the instance of T given by this.
      • 그렇지 않으면 결과는 @ no__t-0의 연결 된 인스턴스 식이 있는 속성 액세스입니다.Otherwise, the result is a property access with an associated instance expression of E.
    • @No__t-0이 class_type I는 해당 class_type의 인스턴스 필드를 식별 합니다.If T is a class_type and I identifies an instance field of that class_type:
      • @No__t-0의 값이-1 @no__t 이면 System.NullReferenceException가 throw 됩니다.If the value of E is null, then a System.NullReferenceException is thrown.
      • 그렇지 않고 필드가-0 @no__t 인 경우 필드가 선언 된 클래스의 인스턴스 생성자 외부에서 참조가 발생 하는 경우 결과는 값, 즉 @ no__t-2에서 참조 하는 개체의 @ no__t-1 필드 값입니다.Otherwise, if the field is readonly and the reference occurs outside an instance constructor of the class in which the field is declared, then the result is a value, namely the value of the field I in the object referenced by E.
      • 그렇지 않으면 결과는 변수가 됩니다. 즉, @ no__t-1에서 참조 하는 개체의 @ no__t-0 필드를 반환 합니다.Otherwise, the result is a variable, namely the field I in the object referenced by E.
    • @No__t-0이 struct_type I는 해당 struct_type의 인스턴스 필드를 식별 합니다.If T is a struct_type and I identifies an instance field of that struct_type:
      • @No__t-0이 값 이거나 필드가-1 @no__t 고 필드가 선언 된 구조체의 인스턴스 생성자 외부에서 참조가 발생 하는 경우 결과는 @ no__t-3에 지정 된 구조체 인스턴스의 @ no__t-2 필드 값과 같은 값입니다.If E is a value, or if the field is readonly and the reference occurs outside an instance constructor of the struct in which the field is declared, then the result is a value, namely the value of the field I in the struct instance given by E.
      • 그렇지 않으면 결과는 변수가 됩니다. 즉, @ no__t-1로 지정 된 구조체 인스턴스의 @ no__t-0 필드를 반환 합니다.Otherwise, the result is a variable, namely the field I in the struct instance given by E.
    • @No__t-0 인 경우 인스턴스 이벤트를 식별 합니다.If I identifies an instance event:
      • 이벤트가 선언 된 클래스 또는 구조체 내에서 참조가 발생 하 고 이벤트가 event_accessor_declarations (이벤트) 없이 선언 되었으며 참조가 += 또는 -= 연산자의 왼쪽으로 발생 하지 않는 경우 E.II가 인스턴스 필드인 것 처럼 처리 됩니다.If the reference occurs within the class or struct in which the event is declared, and the event was declared without event_accessor_declarations (Events), and the reference does not occur as the left-hand side of a += or -= operator, then E.I is processed exactly as if I was an instance field.
      • 그렇지 않으면 결과는 @ no__t-0의 연결 된 인스턴스 식이 있는 이벤트 액세스입니다.Otherwise, the result is an event access with an associated instance expression of E.
  • 그렇지 않으면 E.I을 확장 메서드 호출 (확장 메서드 호출)로 처리 하려고 시도 합니다.Otherwise, an attempt is made to process E.I as an extension method invocation (Extension method invocations). 이 작업이 실패 하면 E.I은 잘못 된 멤버 참조 이며 바인딩 시간 오류가 발생 합니다.If this fails, E.I is an invalid member reference, and a binding-time error occurs.

동일한 단순 이름 및 형식 이름Identical simple names and type names

@No__t-0 형식의 멤버 액세스에서 E이 단일 식별자이 고, E의 의미가 simple_name (단순 이름) 인 경우에는 E의 의미와 동일한 형식의 상수, 필드, 속성, 지역 변수 또는 매개 변수입니다. type_name (네임 스페이스 및 형식 이름) E의 가능한 의미가 모두 허용 됩니다.In a member access of the form E.I, if E is a single identifier, and if the meaning of E as a simple_name (Simple names) is a constant, field, property, local variable, or parameter with the same type as the meaning of E as a type_name (Namespace and type names), then both possible meanings of E are permitted. @No__t-1은 두 경우 모두 E 형식의 멤버 여야 하므로 @no__t의 두 가지 가능한 의미는 모호 하지 않습니다.The two possible meanings of E.I are never ambiguous, since I must necessarily be a member of the type E in both cases. 즉, 규칙은 정적 멤버에 대 한 액세스를 허용 하 고, E의 중첩 된 형식에만 액세스를 허용 합니다 .이 경우 컴파일 타임 오류가 발생 합니다.In other words, the rule simply permits access to the static members and nested types of E where a compile-time error would otherwise have occurred. 예를 들어 다음과 같은 가치를 제공해야 합니다.For example:

struct Color
{
    public static readonly Color White = new Color(...);
    public static readonly Color Black = new Color(...);

    public Color Complement() {...}
}

class A
{
    public Color Color;                // Field Color of type Color

    void F() {
        Color = Color.Black;           // References Color.Black static member
        Color = Color.Complement();    // Invokes Complement() on Color field
    }

    static void G() {
        Color c = Color.White;         // References Color.White static member
    }
}

문법 모호성Grammar ambiguities

Simple_name (단순 이름) 및 member_access (멤버 액세스)에 대 한 생성은 식의 문법에서 모호성을 증가 시킬 수 있습니다.The productions for simple_name (Simple names) and member_access (Member access) can give rise to ambiguities in the grammar for expressions. 예를 들어 문은 다음과 같습니다.For example, the statement:

F(G<A,B>(7));

는 두 개의 인수 (G < AB > (7))를 사용 하는 @no__t에 대 한 호출로 해석 될 수 있습니다.could be interpreted as a call to F with two arguments, G < A and B > (7). 또는 하나의 인수를 사용 하는 @no__t에 대 한 호출로 해석 될 수 있습니다. 즉, 두 개의 형식 인수와 하나의 일반 인수가 있는 제네릭 메서드 @ no__t-1에 대 한 호출입니다.Alternatively, it could be interpreted as a call to F with one argument, which is a call to a generic method G with two type arguments and one regular argument.

토큰 시퀀스를 simple_name (단순 이름), member_access (멤버 액세스) 또는 pointer_member_access (포인터 멤버 액세스) type_argument_로 끝나는 구문 분석할 수 있는 경우 목록 (형식 인수), 닫는 > 토큰 바로 다음에 오는 토큰이 검사 됩니다.If a sequence of tokens can be parsed (in context) as a simple_name (Simple names), member_access (Member access), or pointer_member_access (Pointer member access) ending with a type_argument_list (Type arguments), the token immediately following the closing > token is examined. 다음 중 하나인 경우If it is one of

(  )  ]  }  :  ;  ,  .  ?  ==  !=  |  ^

그런 다음 type_argument_listsimple_name, member_access 또는 pointer_member_access 의 일부로 유지 되 고 토큰 시퀀스의 다른 모든 구문 분석은 무시 됩니다.then the type_argument_list is retained as part of the simple_name, member_access or pointer_member_access and any other possible parse of the sequence of tokens is discarded. 그렇지 않으면 type_argument_list 는 토큰 시퀀스에 대 한 다른 가능한 구문 분석이 없더라도 simple_name, member_access 또는 pointer_member_access의 일부로 간주 되지 않습니다.Otherwise, the type_argument_list is not considered to be part of the simple_name, member_access or pointer_member_access, even if there is no other possible parse of the sequence of tokens. Namespace_or_type_name (네임 스페이스 및 형식 이름)에서 type_argument_list 를 구문 분석할 때는 이러한 규칙이 적용 되지 않습니다.Note that these rules are not applied when parsing a type_argument_list in a namespace_or_type_name (Namespace and type names). 다음 문은The statement

F(G<A,B>(7));

는이 규칙에 따라 인수 하나를 사용 하 여 F에 대 한 호출로 해석 됩니다 .이 인수는 제네릭 메서드를 호출 하는 두 개의 형식 인수 및 하나의 일반 인수가 있는 G입니다.will, according to this rule, be interpreted as a call to F with one argument, which is a call to a generic method G with two type arguments and one regular argument. The statements

F(G < A, B > 7);
F(G < A, B >> 7);

는 두 개의 인수를 사용 하 여 F에 대 한 호출로 해석 됩니다.will each be interpreted as a call to F with two arguments. 다음 문은The statement

x = F < A > +y;

type_argument_list 를 사용 하는 simple_name 와 이항 더하기 연산자가 오는 것이 아니라-0 @no__t 작성 된 것 처럼 보다 작음 연산자, 보다 큼 연산자 및 단항 더하기 연산자로 해석 됩니다.will be interpreted as a less than operator, greater than operator, and unary plus operator, as if the statement had been written x = (F < A) > (+y), instead of as a simple_name with a type_argument_list followed by a binary plus operator. 문에서In the statement

x = y is C<T> + z;

토큰 C<T>type_argument_list를 사용 하 여 namespace_or_type_name 해석 됩니다.the tokens C<T> are interpreted as a namespace_or_type_name with a type_argument_list.

호출 식Invocation expressions

Invocation_expression 는 메서드를 호출 하는 데 사용 됩니다.An invocation_expression is used to invoke a method.

invocation_expression
    : primary_expression '(' argument_list? ')'
    ;

Invocation_expression 은 다음 중 하나 이상에 해당 하는 경우 동적으로 바인딩됩니다 (동적 바인딩).An invocation_expression is dynamically bound (Dynamic binding) if at least one of the following holds:

  • Primary_expression 에는 컴파일 타임 형식 dynamic이 있습니다.The primary_expression has compile-time type dynamic.
  • 선택적 argument_list 의 인수 중 하나 이상에 컴파일 타임 형식 dynamic이 있고 primary_expression 에 대리자 형식이 없는 경우At least one argument of the optional argument_list has compile-time type dynamic and the primary_expression does not have a delegate type.

이 경우 컴파일러는 invocation_expression 을 @no__t 형식의 값으로 분류 합니다.In this case the compiler classifies the invocation_expression as a value of type dynamic. 그런 다음 invocation_expression 의 의미를 확인 하는 규칙은 런타임에 컴파일 시간 형식이 있는 primary_expression 및 인수에 대 한 컴파일 시간 형식 대신 런타임 형식을 사용 하 여 적용 됩니다 @no_ _t-2.The rules below to determine the meaning of the invocation_expression are then applied at run-time, using the run-time type instead of the compile-time type of those of the primary_expression and arguments which have the compile-time type dynamic. Primary_expression 에 컴파일 시간 @no__t 형식이 없는 경우에는 동적 오버 로드 확인의 컴파일 시간 검사에 설명 된 대로 메서드 호출에서 제한 된 컴파일 시간 검사를 수행 합니다.If the primary_expression does not have compile-time type dynamic, then the method invocation undergoes a limited compile time check as described in Compile-time checking of dynamic overload resolution.

Invocation_expressionprimary_expression 은 메서드 그룹 이거나 delegate_type의 값 이어야 합니다.The primary_expression of an invocation_expression must be a method group or a value of a delegate_type. Primary_expression 가 메서드 그룹인 경우 invocation_expression 는 메서드 호출 (메서드 호출)입니다.If the primary_expression is a method group, the invocation_expression is a method invocation (Method invocations). Primary_expressiondelegate_type값 이면 Invocation_expression 는 대리자 호출 (대리자호출)입니다.If the primary_expression is a value of a delegate_type, the invocation_expression is a delegate invocation (Delegate invocations). Primary_expression 가 메서드 그룹이 아니거나 delegate_type의 값이 아닌 경우에는 바인딩 시간 오류가 발생 합니다.If the primary_expression is neither a method group nor a value of a delegate_type, a binding-time error occurs.

선택적 argument_list (인수 목록)은 메서드의 매개 변수에 대 한 값 또는 변수 참조를 제공 합니다.The optional argument_list (Argument lists) provides values or variable references for the parameters of the method.

Invocation_expression 평가 결과는 다음과 같이 분류 됩니다.The result of evaluating an invocation_expression is classified as follows:

  • Invocation_expressionvoid을 반환 하는 메서드 또는 대리자를 호출 하는 경우 결과는 nothing입니다.If the invocation_expression invokes a method or delegate that returns void, the result is nothing. Nothing으로 분류 된 식은 statement_expression (식 문)의 컨텍스트나 lambda_expression (익명 함수 식)의 본문 으로만 허용 됩니다.An expression that is classified as nothing is permitted only in the context of a statement_expression (Expression statements) or as the body of a lambda_expression (Anonymous function expressions). 그렇지 않으면 바인딩 타임 오류가 발생 합니다.Otherwise a binding-time error occurs.
  • 그렇지 않으면 결과는 메서드나 대리자가 반환 하는 형식의 값입니다.Otherwise, the result is a value of the type returned by the method or delegate.

메서드 호출Method invocations

메서드 호출의 경우 invocation_expressionprimary_expression 는 메서드 그룹 이어야 합니다.For a method invocation, the primary_expression of the invocation_expression must be a method group. 메서드 그룹은 호출할 특정 메서드를 선택 하는 오버 로드 된 메서드 집합 또는 호출할 한 메서드를 식별 합니다.The method group identifies the one method to invoke or the set of overloaded methods from which to choose a specific method to invoke. 후자의 경우 호출할 특정 메서드를 결정 하는 것은 argument_list의 인수 형식에서 제공 하는 컨텍스트를 기반으로 합니다.In the latter case, determination of the specific method to invoke is based on the context provided by the types of the arguments in the argument_list.

@No__t 폼의 메서드 호출에 대 한 바인딩 시간 처리 (M은 메서드 그룹 ( type_argument_list포함 될 수 있음)이 *고, @no__t*-3은 다음 단계로 구성 됩니다.The binding-time processing of a method invocation of the form M(A), where M is a method group (possibly including a type_argument_list), and A is an optional argument_list, consists of the following steps:

  • 메서드 호출에 대 한 후보 메서드 집합이 생성 됩니다.The set of candidate methods for the method invocation is constructed. 메서드 그룹에 연결 된 F은-1 @no__t 합니다.For each method F associated with the method group M:
    • @No__t-0이 제네릭이 아닌 경우 다음을 수행 하는 경우-1 @no__t.If F is non-generic, F is a candidate when:
    • @No__t-0이 제네릭이 고 M에 형식 인수 목록이 없는 경우 F는 다음과 같은 후보입니다.If F is generic and M has no type argument list, F is a candidate when:
      • 형식 유추 (형식 유추)가 성공 하 고, 호출에 대 한 형식 인수 목록을 유추 하 고,Type inference (Type inference) succeeds, inferring a list of type arguments for the call, and
      • 유추 된 형식 인수가 해당 메서드 형식 매개 변수로 대체 되 면 F의 매개 변수 목록에 생성 된 모든 형식이 제약 조건 (만족 제약 조건)을 충족 하 고 F의 매개 변수 목록을 사용할 수 있습니다. A (적용 가능한 함수 멤버)와 관련 됩니다.Once the inferred type arguments are substituted for the corresponding method type parameters, all constructed types in the parameter list of F satisfy their constraints (Satisfying constraints), and the parameter list of F is applicable with respect to A (Applicable function member).
    • @No__t-0이 제네릭이 고 M은 형식 인수 목록을 포함 하는 경우 다음을 수행 하는 경우 F가 후보가 됩니다.If F is generic and M includes a type argument list, F is a candidate when:
      • F에는 형식 인수 목록에 제공 된 것과 동일한 수의 메서드 형식 매개 변수가 있습니다.F has the same number of method type parameters as were supplied in the type argument list, and
      • 형식 인수가 해당 메서드 형식 매개 변수로 대체 되 면 F의 매개 변수 목록에 생성 된 모든 형식이 제약 조건 (만족 제약 조건)을 충족 하 고 F의 매개 변수 목록은와 관련 하 여 적용할 수 있습니다. A (적용 가능한 함수 멤버).Once the type arguments are substituted for the corresponding method type parameters, all constructed types in the parameter list of F satisfy their constraints (Satisfying constraints), and the parameter list of F is applicable with respect to A (Applicable function member).
  • 후보 메서드 집합은 가장 많이 파생 된 형식의 메서드만 포함 하도록 줄어듭니다. @No__t 집합의 각 메서드 C.FF 메서드가 선언 된 형식입니다.-1은 C의 기본 형식에 선언 된 모든 메서드는 집합에서 제거 됩니다.The set of candidate methods is reduced to contain only methods from the most derived types: For each method C.F in the set, where C is the type in which the method F is declared, all methods declared in a base type of C are removed from the set. 또한 Cobject 이외의 클래스 형식인 경우 인터페이스 형식에 선언 된 모든 메서드는 집합에서 제거 됩니다.Furthermore, if C is a class type other than object, all methods declared in an interface type are removed from the set. 이 두 번째 규칙은 메서드 그룹이 개체 및 비어 있지 않은 유효 인터페이스 집합이 아닌 유효한 기본 클래스를 가진 형식 매개 변수에 대 한 멤버 조회의 결과인 경우에만 적용 됩니다.(This latter rule only has affect when the method group was the result of a member lookup on a type parameter having an effective base class other than object and a non-empty effective interface set.)
  • 결과 후보 메서드 집합이 비어 있는 경우 다음 단계를 따라 추가 처리가 중단 되 고 대신 확장 메서드 호출 (확장 메서드호출)로 호출을 처리 하려고 시도 합니다.If the resulting set of candidate methods is empty, then further processing along the following steps are abandoned, and instead an attempt is made to process the invocation as an extension method invocation (Extension method invocations). 이 작업이 실패 하면 적용 가능한 메서드가 없으며 바인딩 시간 오류가 발생 합니다.If this fails, then no applicable methods exist, and a binding-time error occurs.
  • 후보 메서드 집합의 모범 메서드는 오버 로드 확인의오버 로드 확인 규칙을 사용 하 여 식별 됩니다.The best method of the set of candidate methods is identified using the overload resolution rules of Overload resolution. 단일 최상의 방법을 식별할 수 없는 경우 메서드 호출이 모호 하 고 바인딩 시간 오류가 발생 합니다.If a single best method cannot be identified, the method invocation is ambiguous, and a binding-time error occurs. 오버 로드 확인을 수행할 때 해당 메서드 형식 매개 변수에 대해 제공 되거나 유추 된 형식 인수를 대체 한 후 제네릭 메서드의 매개 변수를 고려 합니다.When performing overload resolution, the parameters of a generic method are considered after substituting the type arguments (supplied or inferred) for the corresponding method type parameters.
  • 선택한 최상의 방법의 최종 유효성 검사가 수행 됩니다.Final validation of the chosen best method is performed:
    • 메서드 그룹의 컨텍스트에서 메서드의 유효성을 검사 합니다. 최적의 메서드가 정적 메서드인 경우 메서드 그룹은 simple_name 또는 member_access 에서 형식을 통해 생성 된 것 이어야 합니다.The method is validated in the context of the method group: If the best method is a static method, the method group must have resulted from a simple_name or a member_access through a type. 가장 좋은 방법이 인스턴스 메서드인 경우 메서드 그룹은 simple_name, 변수 또는 값을 통해 member_access 또는 base_access에서 발생 해야 합니다.If the best method is an instance method, the method group must have resulted from a simple_name, a member_access through a variable or value, or a base_access. 이러한 요구 사항이 모두 충족 되지 않으면 바인딩 시간 오류가 발생 합니다.If neither of these requirements is true, a binding-time error occurs.
    • 가장 좋은 메서드가 제네릭 메서드인 경우 제네릭 메서드에 선언 된 제약 조건 (만족 제약 조건)에 대해 형식 인수 (제공 되거나 유추 된)를 확인 합니다.If the best method is a generic method, the type arguments (supplied or inferred) are checked against the constraints (Satisfying constraints) declared on the generic method. 형식 인수가 형식 매개 변수의 해당 제약 조건을 충족 하지 않으면 바인딩 시간 오류가 발생 합니다.If any type argument does not satisfy the corresponding constraint(s) on the type parameter, a binding-time error occurs.

메서드를 선택 하 고 바인딩 시간에 위의 단계에 따라 유효성을 검사 한 후에는 동적 오버 로드 확인의 컴파일 타임 검사에 설명 된 함수 멤버 호출의 규칙에 따라 실제 런타임 호출이 처리 됩니다.Once a method has been selected and validated at binding-time by the above steps, the actual run-time invocation is processed according to the rules of function member invocation described in Compile-time checking of dynamic overload resolution.

위에서 설명한 해결 규칙의 직관적인 효과는 다음과 같습니다. 메서드 호출에 의해 호출 되는 특정 메서드를 찾으려면 메서드 호출에 지정 된 형식으로 시작 하 고, 하나 이상의 해당 하는 액세스 가능 하 고 재정의 되지 않은 메서드 선언이 발견 될 때까지 상속 체인을 진행 합니다.The intuitive effect of the resolution rules described above is as follows: To locate the particular method invoked by a method invocation, start with the type indicated by the method invocation and proceed up the inheritance chain until at least one applicable, accessible, non-override method declaration is found. 그런 다음 해당 형식에서 선언 된 적용 가능 하 고, 액세스 가능한 재정의 메서드 집합에 대해 형식 유추 및 오버 로드 확인을 수행 하 고,이를 선택 하 여 메서드를 호출 합니다.Then perform type inference and overload resolution on the set of applicable, accessible, non-override methods declared in that type and invoke the method thus selected. 메서드를 찾을 수 없으면 호출을 확장 메서드 호출로 처리 하는 대신 시도 합니다.If no method was found, try instead to process the invocation as an extension method invocation.

확장 메서드 호출Extension method invocations

형식 중 하나의 메서드 호출 (boxed 인스턴스에 대 한 호출)In a method invocation (Invocations on boxed instances) of one of the forms

expr . identifier ( )

expr . identifier ( args )

expr . identifier < typeargs > ( )

expr . identifier < typeargs > ( args )

호출의 정상적인 처리에서 적용 가능한 메서드를 찾지 못하면 확장 메서드 호출로 구문을 처리 하려고 시도 합니다.if the normal processing of the invocation finds no applicable methods, an attempt is made to process the construct as an extension method invocation. Expr 또는 args 에 컴파일 시간 형식이 dynamic 인 경우 확장 메서드는 적용 되지 않습니다.If expr or any of the args has compile-time type dynamic, extension methods will not apply.

목표는 해당 정적 메서드 호출이 수행 될 수 있도록 가장 적합 한 type_name C을 찾는 것입니다.The objective is to find the best type_name C, so that the corresponding static method invocation can take place:

C . identifier ( expr )

C . identifier ( expr , args )

C . identifier < typeargs > ( expr )

C . identifier < typeargs > ( expr , args )

@No__t 확장 메서드는 다음과 같은 경우에 적합 합니다.An extension method Ci.Mj is eligible if:

  • Ci은 제네릭이 아닌 비중첩 클래스입니다.Ci is a non-generic, non-nested class
  • @No__t의 이름은 식별자입니다. 0은 식별자 입니다.The name of Mj is identifier
  • 위에 표시 된 것 처럼 Mj은 액세스할 수 있으며 인수에 정적 메서드로 적용 될 때 적용할 수 있습니다.Mj is accessible and applicable when applied to the arguments as a static method as shown above
  • Expr 에서 Mj의 첫 번째 매개 변수 형식으로 암시적 id, 참조 또는 boxing 변환이 존재 합니다.An implicit identity, reference or boxing conversion exists from expr to the type of the first parameter of Mj.

@No__t-0에 대 한 검색은 다음과 같이 진행 됩니다.The search for C proceeds as follows:

  • 가장 가까운 바깥쪽 네임 스페이스 선언부터 시작 하 여 각 바깥쪽 네임 스페이스 선언을 계속 하 고 포함 하는 컴파일 단위를 사용 하 여 종료 하면 확장 메서드의 후보 집합을 찾으려고 합니다.Starting with the closest enclosing namespace declaration, continuing with each enclosing namespace declaration, and ending with the containing compilation unit, successive attempts are made to find a candidate set of extension methods:
    • 지정 된 네임 스페이스 또는 컴파일 단위에 비 제네릭 형식 선언이 직접 포함 되어 있는 경우 (적합 한 확장 메서드를 사용 하는-0 Mj @no__t) 해당 확장 메서드 집합이 후보 집합입니다.If the given namespace or compilation unit directly contains non-generic type declarations Ci with eligible extension methods Mj, then the set of those extension methods is the candidate set.
    • Using_static_declarations 에서 가져오고 지정 된 네임 스페이스의 using_namespace_directives로 가져온 네임 스페이스에서 직접 선언 된 형식 @no__t 경우에는-3 @no__t 적합 한 확장 메서드를 직접 포함 합니다. 이러한 확장 메서드 집합은 후보 집합입니다.If types Ci imported by using_static_declarations and directly declared in namespaces imported by using_namespace_directives in the given namespace or compilation unit directly contain eligible extension methods Mj, then the set of those extension methods is the candidate set.
  • 바깥쪽 네임 스페이스 선언 또는 컴파일 단위에서 후보 집합을 찾을 수 없는 경우 컴파일 타임 오류가 발생 합니다.If no candidate set is found in any enclosing namespace declaration or compilation unit, a compile-time error occurs.
  • 그렇지 않으면 오버 로드 확인은 (오버 로드 확인)에 설명 된 대로 설정 된 후보에 적용 됩니다.Otherwise, overload resolution is applied to the candidate set as described in (Overload resolution). 단일 최상의 메서드를 찾을 수 없는 경우 컴파일 타임 오류가 발생 합니다.If no single best method is found, a compile-time error occurs.
  • C은 가장 적합 한 메서드가 확장 메서드로 선언 되는 형식입니다.C is the type within which the best method is declared as an extension method.

대상으로 C을 사용 하면 메서드 호출이 정적 메서드 호출로 처리 됩니다 (동적 오버 로드 확인의 컴파일 시간 검사).Using C as a target, the method call is then processed as a static method invocation (Compile-time checking of dynamic overload resolution).

앞의 규칙은 인스턴스 메서드가 확장 메서드 보다 우선적으로 적용 되 고, 내부 네임 스페이스 선언에서 사용할 수 있는 확장 메서드가 외부 네임 스페이스 선언에서 사용할 수 있는 확장 메서드 보다 우선적으로 적용 되며, 해당 확장입니다. 네임 스페이스에서 직접 선언 된 메서드는 using 네임 스페이스 지시문을 사용 하 여 동일한 네임 스페이스로 가져온 확장 메서드 보다 우선 적용 됩니다.The preceding rules mean that instance methods take precedence over extension methods, that extension methods available in inner namespace declarations take precedence over extension methods available in outer namespace declarations, and that extension methods declared directly in a namespace take precedence over extension methods imported into that same namespace with a using namespace directive. 예를 들어 다음과 같은 가치를 제공해야 합니다.For example:

public static class E
{
    public static void F(this object obj, int i) { }

    public static void F(this object obj, string s) { }
}

class A { }

class B
{
    public void F(int i) { }
}

class C
{
    public void F(object obj) { }
}

class X
{
    static void Test(A a, B b, C c) {
        a.F(1);              // E.F(object, int)
        a.F("hello");        // E.F(object, string)

        b.F(1);              // B.F(int)
        b.F("hello");        // E.F(object, string)

        c.F(1);              // C.F(object)
        c.F("hello");        // C.F(object)
    }
}

이 예제에서 B의 메서드는 첫 번째 확장 메서드 보다 우선적으로 적용 되 고 C의 메서드는 두 확장 메서드 보다 우선적으로 적용 됩니다.In the example, B's method takes precedence over the first extension method, and C's method takes precedence over both extension methods.

public static class C
{
    public static void F(this int i) { Console.WriteLine("C.F({0})", i); }
    public static void G(this int i) { Console.WriteLine("C.G({0})", i); }
    public static void H(this int i) { Console.WriteLine("C.H({0})", i); }
}

namespace N1
{
    public static class D
    {
        public static void F(this int i) { Console.WriteLine("D.F({0})", i); }
        public static void G(this int i) { Console.WriteLine("D.G({0})", i); }
    }
}

namespace N2
{
    using N1;

    public static class E
    {
        public static void F(this int i) { Console.WriteLine("E.F({0})", i); }
    }

    class Test
    {
        static void Main(string[] args)
        {
            1.F();
            2.G();
            3.H();
        }
    }
}

이 예제의 출력은 다음과 같습니다.The output of this example is:

E.F(1)
D.G(2)
C.H(3)

D.GC.G 보다 우선적으로 적용 되 고, E.FD.FC.F 모두에 우선 합니다.D.G takes precedence over C.G, and E.F takes precedence over both D.F and C.F.

대리자 호출Delegate invocations

대리자 호출의 경우 invocation_expressionprimary_expressiondelegate_type의 값 이어야 합니다.For a delegate invocation, the primary_expression of the invocation_expression must be a value of a delegate_type. 또한 delegate_typedelegate_type과 동일한 매개 변수 목록을 사용 하는 함수 멤버로 간주 하는 것을 고려 하 여 delegate_type 에 대해 적용 가능한 함수 멤버 (해당함수 멤버)를 적용 해야 합니다. invocation_expression의 목록입니다.Furthermore, considering the delegate_type to be a function member with the same parameter list as the delegate_type, the delegate_type must be applicable (Applicable function member) with respect to the argument_list of the invocation_expression.

@No__t 폼의 대리자 호출에 대 한 런타임 처리 (Ddelegate_typeprimary_expression 이 *고, @no__t*-4는 다음과 같은 단계로 구성 됩니다.The run-time processing of a delegate invocation of the form D(A), where D is a primary_expression of a delegate_type and A is an optional argument_list, consists of the following steps:

  • D이 계산 됩니다.D is evaluated. 이 평가에서 예외가 발생 하면 추가 단계가 실행 되지 않습니다.If this evaluation causes an exception, no further steps are executed.
  • @No__t-0의 값이 유효한 지 확인 합니다.The value of D is checked to be valid. @No__t-0의 값이-1 @no__t 이면 System.NullReferenceException가 throw 되며 추가 단계가 실행 되지 않습니다.If the value of D is null, a System.NullReferenceException is thrown and no further steps are executed.
  • 그렇지 않으면 D은 대리자 인스턴스에 대 한 참조입니다.Otherwise, D is a reference to a delegate instance. 대리자의 호출 목록에 있는 각 호출 가능 엔터티에서 함수 멤버 호출 (동적 오버 로드 확인의 컴파일 타임 확인)이 수행 됩니다.Function member invocations (Compile-time checking of dynamic overload resolution) are performed on each of the callable entities in the invocation list of the delegate. 인스턴스 및 인스턴스 메서드로 구성 된 호출 가능 엔터티의 경우 호출에 대 한 인스턴스는 호출 가능 엔터티에 포함 된 인스턴스입니다.For callable entities consisting of an instance and instance method, the instance for the invocation is the instance contained in the callable entity.

요소 액세스Element access

Element_accessprimary_no_array_creation_expression으로 구성 되 고 그 뒤에는 "[" 토큰이 오고 그 뒤 에는 " ]" 토큰이 나옵니다.An element_access consists of a primary_no_array_creation_expression, followed by a "[" token, followed by an argument_list, followed by a "]" token. Argument_list 는 하나 이상의 인수로구성 되며 쉼표로 구분 됩니다.The argument_list consists of one or more arguments, separated by commas.

element_access
    : primary_no_array_creation_expression '[' expression_list ']'
    ;

Element_accessargument_listref 또는 out 인수를 포함할 수 없습니다.The argument_list of an element_access is not allowed to contain ref or out arguments.

Element_access 은 다음 중 하나 이상에 해당 하는 경우 동적으로 바인딩됩니다 (동적 바인딩).An element_access is dynamically bound (Dynamic binding) if at least one of the following holds:

  • Primary_no_array_creation_expression 에는 컴파일 타임 형식 dynamic이 있습니다.The primary_no_array_creation_expression has compile-time type dynamic.
  • Argument_list 의 식 중 하나 이상에 컴파일 타임 형식 dynamic이 있고 primary_no_array_creation_expression 에 배열 형식이 없습니다.At least one expression of the argument_list has compile-time type dynamic and the primary_no_array_creation_expression does not have an array type.

이 경우 컴파일러는 element_access 을 @no__t 형식의 값으로 분류 합니다.In this case the compiler classifies the element_access as a value of type dynamic. 그런 다음 element_access 의 의미를 확인 하는 규칙은 런타임에 primary_no_array_creation_expressionargument_list 의 컴파일 시간 형식 대신 런타임 형식을 사용 하 여 적용 됩니다. 컴파일 시간 형식이 dynamic 인 식입니다.The rules below to determine the meaning of the element_access are then applied at run-time, using the run-time type instead of the compile-time type of those of the primary_no_array_creation_expression and argument_list expressions which have the compile-time type dynamic. Primary_no_array_creation_expression 에 컴파일 시간 형식이 dynamic 인 경우에는 동적 오버 로드 확인의 컴파일 시간 검사에 설명 된 대로 요소 액세스에 제한 된 컴파일 시간 검사가 수행 됩니다.If the primary_no_array_creation_expression does not have compile-time type dynamic, then the element access undergoes a limited compile time check as described in Compile-time checking of dynamic overload resolution.

Element_accessprimary_no_array_creation_expressionarray_type값 이면 element_access 는 배열 액세스 (배열 액세스)입니다.If the primary_no_array_creation_expression of an element_access is a value of an array_type, the element_access is an array access (Array access). 그렇지 않은 경우 primary_no_array_creation_expression 는 하나 이상의 인덱서 멤버가 있는 클래스, 구조체 또는 인터페이스 형식의 값 또는 변수 여야 합니다 .이 경우 element_access 는 인덱서 액세스 (인덱서 액세스)입니다.Otherwise, the primary_no_array_creation_expression must be a variable or value of a class, struct, or interface type that has one or more indexer members, in which case the element_access is an indexer access (Indexer access).

배열 액세스Array access

배열 액세스의 경우 element_accessprimary_no_array_creation_expressionarray_type의 값 이어야 합니다.For an array access, the primary_no_array_creation_expression of the element_access must be a value of an array_type. 또한 배열 액세스 argument_list 에는 명명 된 인수를 포함할 수 없습니다. Argument_list 의 식 수는 array_type의 순위와 동일 해야 하며, 각 식은 int, uint @no__t, ulong 형식 이어야 합니다. 또는 이러한 형식 중 하나 이상으로 암시적으로 변환할 수 있어야 합니다.Furthermore, the argument_list of an array access is not allowed to contain named arguments.The number of expressions in the argument_list must be the same as the rank of the array_type, and each expression must be of type int, uint, long, ulong, or must be implicitly convertible to one or more of these types.

배열 액세스를 평가한 결과는 배열의 요소 형식, 즉 argument_list에 있는 식의 값에 의해 선택 된 배열 요소입니다.The result of evaluating an array access is a variable of the element type of the array, namely the array element selected by the value(s) of the expression(s) in the argument_list.

@No__t 폼의 배열 액세스의 런타임 처리 (Parray_typeprimary_no_array_creation_expression 이 *고, @no__t*-4는 다음 단계로 구성 됩니다.The run-time processing of an array access of the form P[A], where P is a primary_no_array_creation_expression of an array_type and A is an argument_list, consists of the following steps:

  • P이 계산 됩니다.P is evaluated. 이 평가에서 예외가 발생 하면 추가 단계가 실행 되지 않습니다.If this evaluation causes an exception, no further steps are executed.
  • Argument_list 의 인덱스 식은 순서 대로 왼쪽에서 오른쪽으로 계산 됩니다.The index expressions of the argument_list are evaluated in order, from left to right. 각 인덱스 식을 평가 하는 다음 형식 중 하나에 대 한 암시적 변환 (암시적변환)이 수행 됩니다. int, uint, long, ulong입니다.Following evaluation of each index expression, an implicit conversion (Implicit conversions) to one of the following types is performed: int, uint, long, ulong. 이 목록에서 암시적 변환이 있는 첫 번째 형식이 선택 됩니다.The first type in this list for which an implicit conversion exists is chosen. 예를 들어 인덱스 식의 형식이 short 인 경우에는 short에서 int으로, short에서 long로의 암시적 변환이 가능 하기 때문에 int로의 암시적 변환이 수행 됩니다.For instance, if the index expression is of type short then an implicit conversion to int is performed, since implicit conversions from short to int and from short to long are possible. 인덱스 식 또는 후속 암시적 변환에서 예외가 발생 하는 경우에는 더 이상 인덱스 식이 계산 되지 않고 추가 단계가 실행 되지 않습니다.If evaluation of an index expression or the subsequent implicit conversion causes an exception, then no further index expressions are evaluated and no further steps are executed.
  • @No__t-0의 값이 유효한 지 확인 합니다.The value of P is checked to be valid. @No__t-0의 값이-1 @no__t 이면 System.NullReferenceException가 throw 되며 추가 단계가 실행 되지 않습니다.If the value of P is null, a System.NullReferenceException is thrown and no further steps are executed.
  • Argument_list 의 각 식 값은 P로 참조 되는 배열 인스턴스의 실제 범위에 대해 확인 됩니다.The value of each expression in the argument_list is checked against the actual bounds of each dimension of the array instance referenced by P. 하나 이상의 값이 범위를 벗어나면 System.IndexOutOfRangeException이 throw 되 고 추가 단계가 실행 되지 않습니다.If one or more values are out of range, a System.IndexOutOfRangeException is thrown and no further steps are executed.
  • 인덱스 식에 지정 된 배열 요소의 위치가 계산 되며이 위치는 배열 액세스의 결과가 됩니다.The location of the array element given by the index expression(s) is computed, and this location becomes the result of the array access.

인덱서 액세스Indexer access

인덱서 액세스의 경우 element_accessprimary_no_array_creation_expression 는 클래스, 구조체 또는 인터페이스 형식의 변수 또는 값 이어야 하며,이 형식은와 관련 하 여 해당 하는 하나 이상의 인덱서를 구현 해야 합니다. element_accessargument_list 입니다.For an indexer access, the primary_no_array_creation_expression of the element_access must be a variable or value of a class, struct, or interface type, and this type must implement one or more indexers that are applicable with respect to the argument_list of the element_access.

@No__t 폼의 인덱서 액세스에 대 한 바인딩 시간 처리 (P은 클래스, 구조체 또는 인터페이스 형식 T)이 고 Aargument_list 입니다. 위한The binding-time processing of an indexer access of the form P[A], where P is a primary_no_array_creation_expression of a class, struct, or interface type T, and A is an argument_list, consists of the following steps:

  • @No__t-0에서 제공 하는 인덱서 집합이 생성 됩니다.The set of indexers provided by T is constructed. 집합은 @no__t에 선언 된 모든 인덱서 또는 @no__t 2 선언이 아니고 현재 컨텍스트 (멤버 액세스)에서 액세스할 수 있는 T의 기본 형식으로 구성 됩니다.The set consists of all indexers declared in T or a base type of T that are not override declarations and are accessible in the current context (Member access).
  • 이 집합은 해당 하는 인덱서로 줄어들고 다른 인덱서에는 표시 되지 않습니다.The set is reduced to those indexers that are applicable and not hidden by other indexers. 다음 규칙은 집합에서-0 @no__t 각 인덱서에 적용 됩니다. 여기서 S은 인덱서 I가 선언 된 형식입니다.The following rules are applied to each indexer S.I in the set, where S is the type in which the indexer I is declared:
    • @No__t-1 (적용 가능한 함수 멤버)에 대 한 I이 적용 되지 않는 경우에는 I이 집합에서 제거 됩니다.If I is not applicable with respect to A (Applicable function member), then I is removed from the set.
    • @No__t-1 (적용 가능한 함수 멤버)에 대 한 I이 적용 되는 경우 기본 형식 S에 선언 된 모든 인덱서가 집합에서 제거 됩니다.If I is applicable with respect to A (Applicable function member), then all indexers declared in a base type of S are removed from the set.
    • @No__t-1 (적용 가능한 함수 멤버)과 관련 하 여 I이 적용 되 고 Sobject 이외의 클래스 형식인 경우 인터페이스에 선언 된 모든 인덱서는 집합에서 제거 됩니다.If I is applicable with respect to A (Applicable function member) and S is a class type other than object, all indexers declared in an interface are removed from the set.
  • 결과 후보 인덱서의 집합이 비어 있으면 적용 가능한 인덱서가 없고 바인딩 시간 오류가 발생 합니다.If the resulting set of candidate indexers is empty, then no applicable indexers exist, and a binding-time error occurs.
  • 후보 인덱서 집합의 모범 인덱서는 오버 로드 확인의오버 로드 확인 규칙을 사용 하 여 식별 됩니다.The best indexer of the set of candidate indexers is identified using the overload resolution rules of Overload resolution. 최상의 인덱서 하나를 식별할 수 없으면 인덱서 액세스가 모호 하 고 바인딩 시간 오류가 발생 합니다.If a single best indexer cannot be identified, the indexer access is ambiguous, and a binding-time error occurs.
  • Argument_list 의 인덱스 식은 순서 대로 왼쪽에서 오른쪽으로 계산 됩니다.The index expressions of the argument_list are evaluated in order, from left to right. 인덱서 액세스 처리의 결과는 인덱서 액세스로 분류 되는 식입니다.The result of processing the indexer access is an expression classified as an indexer access. 인덱서 액세스 식은 위의 단계에서 결정 된 인덱서를 참조 하며, P의 연결 된 인스턴스 식과 A의 관련 인수 목록이 있습니다.The indexer access expression references the indexer determined in the step above, and has an associated instance expression of P and an associated argument list of A.

인덱서 액세스는 사용 되는 컨텍스트에 따라 get 접근자 또는 인덱서의 set 접근자 를 호출 합니다.Depending on the context in which it is used, an indexer access causes invocation of either the get accessor or the set accessor of the indexer. 인덱서 액세스가 할당의 대상인 경우 set 접근자 를 호출 하 여 새 값 (단순 할당)을 할당 합니다.If the indexer access is the target of an assignment, the set accessor is invoked to assign a new value (Simple assignment). 다른 모든 경우에는 get 접근자 를 호출 하 여 현재 값 (식의 값)을 가져옵니다.In all other cases, the get accessor is invoked to obtain the current value (Values of expressions).

이 액세스This access

This_access 는 예약 된 단어 this로 구성 됩니다.A this_access consists of the reserved word this.

this_access
    : 'this'
    ;

This_access 는 인스턴스 생성자의 블록 , 인스턴스 메서드 또는 인스턴스 접근자 에서만 허용 됩니다.A this_access is permitted only in the block of an instance constructor, an instance method, or an instance accessor. 다음 의미 중 하나입니다.It has one of the following meanings:

  • @No__t-0이 클래스의 인스턴스 생성자 내에서 primary_expression 에 사용 되는 경우 값으로 분류 됩니다.When this is used in a primary_expression within an instance constructor of a class, it is classified as a value. 값의 형식은 사용이 발생 하는 클래스의 인스턴스 형식 (인스턴스 형식)이 고 값은 생성 되는 개체에 대 한 참조입니다.The type of the value is the instance type (The instance type) of the class within which the usage occurs, and the value is a reference to the object being constructed.
  • @No__t-0이 클래스의 인스턴스 메서드 또는 인스턴스 접근자 내의 primary_expression 에서 사용 되는 경우 값으로 분류 됩니다.When this is used in a primary_expression within an instance method or instance accessor of a class, it is classified as a value. 값의 형식은 사용이 발생 하는 클래스의 인스턴스 형식 (인스턴스 형식)이 고, 값은 메서드 또는 접근자를 호출한 개체에 대 한 참조입니다.The type of the value is the instance type (The instance type) of the class within which the usage occurs, and the value is a reference to the object for which the method or accessor was invoked.
  • 구조체의 인스턴스 생성자 내에서 primary_expressionthis이 사용 되 면 변수로 분류 됩니다.When this is used in a primary_expression within an instance constructor of a struct, it is classified as a variable. 변수의 형식은 사용이 발생 하는 구조체의 인스턴스 형식 (인스턴스 형식)이 고, 변수는 생성 되는 구조체를 나타냅니다.The type of the variable is the instance type (The instance type) of the struct within which the usage occurs, and the variable represents the struct being constructed. 구조체의 인스턴스 생성자에 대 한 this 변수는 구조체 형식의 out 매개 변수와 정확히 동일 하 게 동작 합니다. 특히이는 인스턴스 생성자의 모든 실행 경로에 변수가 명확 하 게 할당 되어야 함을 의미 합니다.The this variable of an instance constructor of a struct behaves exactly the same as an out parameter of the struct type—in particular, this means that the variable must be definitely assigned in every execution path of the instance constructor.
  • @No__t-0이 구조체의 인스턴스 메서드 또는 인스턴스 접근자 내의 primary_expression 에서 사용 되는 경우 변수로 분류 됩니다.When this is used in a primary_expression within an instance method or instance accessor of a struct, it is classified as a variable. 변수의 형식은 사용 하는 구조체의 인스턴스 형식 (인스턴스 형식)입니다.The type of the variable is the instance type (The instance type) of the struct within which the usage occurs.
    • 메서드 또는 접근자가반복기 (반복기)가 아닌 경우@no__t 변수는 메서드 또는 접근자가 호출 된 구조체를 나타내며 구조체 형식의 ref 매개 변수와 정확히 동일 하 게 동작 합니다.If the method or accessor is not an iterator (Iterators), the this variable represents the struct for which the method or accessor was invoked, and behaves exactly the same as a ref parameter of the struct type.
    • 메서드 또는 접근자가 반복기 인 경우 this 변수는 메서드 또는 접근자가 호출 된 구조체의 복사본을 나타내며 구조체 형식의 값 매개 변수와 정확히 동일 하 게 동작 합니다.If the method or accessor is an iterator, the this variable represents a copy of the struct for which the method or accessor was invoked, and behaves exactly the same as a value parameter of the struct type.

위에 나열 된 것과 다른 컨텍스트의 primary_expression 에서 this을 사용 하는 것은 컴파일 타임 오류입니다.Use of this in a primary_expression in a context other than the ones listed above is a compile-time error. 특히 정적 메서드, 정적 속성 접근자 또는 필드 선언의 variable_initializer 에서 this을 참조할 수 없습니다.In particular, it is not possible to refer to this in a static method, a static property accessor, or in a variable_initializer of a field declaration.

기본 액세스Base access

Base_access 는 예약어 base과 "." 토큰, 식별자 또는 대괄호로 묶은 argument_list 로 구성 됩니다.A base_access consists of the reserved word base followed by either a "." token and an identifier or an argument_list enclosed in square brackets:

base_access
    : 'base' '.' identifier
    | 'base' '[' expression_list ']'
    ;

Base_access 은 현재 클래스 또는 구조체의 유사 하 게 명명 된 멤버에 의해 숨겨지는 기본 클래스 멤버에 액세스 하는 데 사용 됩니다.A base_access is used to access base class members that are hidden by similarly named members in the current class or struct. Base_access 는 인스턴스 생성자의 블록 , 인스턴스 메서드 또는 인스턴스 접근자 에서만 허용 됩니다.A base_access is permitted only in the block of an instance constructor, an instance method, or an instance accessor. @No__t-0이 클래스 또는 구조체에서 발생 하는 경우 I은 해당 클래스 또는 구조체의 기본 클래스의 멤버를 나타내야 합니다.When base.I occurs in a class or struct, I must denote a member of the base class of that class or struct. 마찬가지로 base[E]이 클래스에서 발생 하면 적용 가능한 인덱서가 기본 클래스에 있어야 합니다.Likewise, when base[E] occurs in a class, an applicable indexer must exist in the base class.

바인딩 타임에 base.Ibase[E] @no__t의 base_access 식은-3 및 ((B)this)[E] 작성 된 것 처럼 정확 하 게 평가 됩니다. 여기서 B는 구문이 발생 하는 클래스 또는 구조체의 기본 클래스입니다.At binding-time, base_access expressions of the form base.I and base[E] are evaluated exactly as if they were written ((B)this).I and ((B)this)[E], where B is the base class of the class or struct in which the construct occurs. 따라서 base.Ibase[E]this.Ithis[E]에 해당 합니다. 단, this는 기본 클래스의 인스턴스로 표시 됩니다.Thus, base.I and base[E] correspond to this.I and this[E], except this is viewed as an instance of the base class.

Base_access 가 가상 함수 멤버 (메서드, 속성 또는 인덱서)를 참조 하는 경우 런타임에 호출할 함수 멤버 (동적 오버 로드 확인의 컴파일 시간 검사)에 대 한 결정이 변경 됩니다.When a base_access references a virtual function member (a method, property, or indexer), the determination of which function member to invoke at run-time (Compile-time checking of dynamic overload resolution) is changed. 호출 되는 함수 멤버는 B과 관련 하 여 함수 멤버의 가장 많이 파생 되는 구현 (가상 메서드)을 찾는 방법으로 결정 됩니다 .이는 this의 런타임 형식과 관련 되지 않고 기본이 아닌 액세스의 경우와 동일 합니다. .The function member that is invoked is determined by finding the most derived implementation (Virtual methods) of the function member with respect to B (instead of with respect to the run-time type of this, as would be usual in a non-base access). 따라서 virtual 함수 멤버의 @no__t 0 내에서 base_access 를 사용 하 여 함수 멤버의 상속 된 구현을 호출할 수 있습니다.Thus, within an override of a virtual function member, a base_access can be used to invoke the inherited implementation of the function member. Base_access 에서 참조 하는 함수 멤버가 abstract 인 경우 바인딩 타임 오류가 발생 합니다.If the function member referenced by a base_access is abstract, a binding-time error occurs.

후위 증가 및 감소 연산자Postfix increment and decrement operators

post_increment_expression
    : primary_expression '++'
    ;

post_decrement_expression
    : primary_expression '--'
    ;

후 위 증가 또는 감소 연산의 피연산자는 변수, 속성 액세스 또는 인덱서 액세스로 분류 된 식 이어야 합니다.The operand of a postfix increment or decrement operation must be an expression classified as a variable, a property access, or an indexer access. 작업의 결과는 피연산자와 동일한 형식의 값입니다.The result of the operation is a value of the same type as the operand.

Primary_expression 에 컴파일 타임 형식 dynamic이 있는 경우 연산자는 동적바인딩 (동적 바인딩)이 고 post_increment_expression 또는 post_decrement_expression 의 컴파일 타임 @no__t 형식은-5입니다. 그리고 런타임에 primary_expression의 런타임 형식을 사용 하 여 다음 규칙이 적용 됩니다.If the primary_expression has the compile-time type dynamic then the operator is dynamically bound (Dynamic binding), the post_increment_expression or post_decrement_expression has the compile-time type dynamic and the following rules are applied at run-time using the run-time type of the primary_expression.

후 위 증가 또는 감소 연산의 피연산자가 속성 또는 인덱서 액세스 인 경우 속성 또는 인덱서에 getset 접근자가 둘 다 있어야 합니다.If the operand of a postfix increment or decrement operation is a property or indexer access, the property or indexer must have both a get and a set accessor. 이러한 경우가 아니면 바인딩 시간 오류가 발생 합니다.If this is not the case, a binding-time error occurs.

특정 연산자 구현을 선택 하기 위해 단항 연산자 오버 로드 확인 (단항 연산자 오버 로드 확인)이 적용 됩니다.Unary operator overload resolution (Unary operator overload resolution) is applied to select a specific operator implementation. 미리 정의 된 ++-- 연산자는 sbyte, byte, short, ushort, int, uint, long, ulong, 0, 1, 2, 3 및 모든 열거형 형식에 대해 존재 합니다.Predefined ++ and -- operators exist for the following types: sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, and any enum type. 미리 정의 된 ++ 연산자는 피연산자에 1을 더하여 생성 된 값을 반환 하 고 미리 정의 된 -- 연산자는 피연산자에서 1을 빼서 생성 된 값을 반환 합니다.The predefined ++ operators return the value produced by adding 1 to the operand, and the predefined -- operators return the value produced by subtracting 1 from the operand. @No__t-0 컨텍스트에서이 더하기 또는 빼기의 결과가 결과 형식의 범위를 벗어나면 결과 형식이 정수 형식 또는 열거형 형식이 면 System.OverflowException이 throw 됩니다.In a checked context, if the result of this addition or subtraction is outside the range of the result type and the result type is an integral type or enum type, a System.OverflowException is thrown.

@No__t-0 또는 x-- 형태의 후 위 증가 또는 감소 연산의 런타임 처리는 다음 단계로 구성 됩니다.The run-time processing of a postfix increment or decrement operation of the form x++ or x-- consists of the following steps:

  • @No__t-0은 변수로 분류 됩니다.If x is classified as a variable:
    • x을 계산 하 여 변수를 생성 합니다.x is evaluated to produce the variable.
    • @No__t-0의 값이 저장 됩니다.The value of x is saved.
    • 선택한 연산자는 인수로 x의 저장 된 값을 사용 하 여 호출 됩니다.The selected operator is invoked with the saved value of x as its argument.
    • 연산자에서 반환 되는 값은 x의 계산에 지정 된 위치에 저장 됩니다.The value returned by the operator is stored in the location given by the evaluation of x.
    • @No__t-0의 저장 된 값은 작업의 결과가 됩니다.The saved value of x becomes the result of the operation.
  • @No__t-0은 속성 또는 인덱서 액세스로 분류 됩니다.If x is classified as a property or indexer access:
    • 인스턴스 식 (xstatic이 아닌 경우) 및 x과 연결 된 인수 목록 (x가 인덱서 액세스 인 경우)이 평가 되 고 이후 getset 접근자 호출에서 결과가 사용 됩니다.The instance expression (if x is not static) and the argument list (if x is an indexer access) associated with x are evaluated, and the results are used in the subsequent get and set accessor invocations.
    • @No__t-1의 get 접근자가 호출 되 고 반환 된 값이 저장 됩니다.The get accessor of x is invoked and the returned value is saved.
    • 선택한 연산자는 인수로 x의 저장 된 값을 사용 하 여 호출 됩니다.The selected operator is invoked with the saved value of x as its argument.
    • @No__t-1의 set 접근자는 연산자가 value 인수로 반환 하는 값으로 호출 됩니다.The set accessor of x is invoked with the value returned by the operator as its value argument.
    • @No__t-0의 저장 된 값은 작업의 결과가 됩니다.The saved value of x becomes the result of the operation.

@No__t-0 및 -- 연산자는 접두사 표기법 (전위 증가 및 감소 연산자)도 지원 합니다.The ++ and -- operators also support prefix notation (Prefix increment and decrement operators). 일반적으로 x++ 또는 x--의 결과는 작업 이전에 x의 값이 고, ++x 또는 --x의 결과는 작업 후에 x의 값입니다.Typically, the result of x++ or x-- is the value of x before the operation, whereas the result of ++x or --x is the value of x after the operation. 두 경우 모두 x은 작업 후에 동일한 값을 갖습니다.In either case, x itself has the same value after the operation.

@No__t-0 또는 operator -- 구현은 후 위 또는 접두사 표기법을 사용 하 여 호출할 수 있습니다.An operator ++ or operator -- implementation can be invoked using either postfix or prefix notation. 두 표기법에 대해 별도의 연산자 구현을 사용할 수 없습니다.It is not possible to have separate operator implementations for the two notations.

new 연산자The new operator

@No__t-0 연산자는 형식의 새 인스턴스를 만드는 데 사용 됩니다.The new operator is used to create new instances of types.

@No__t-0 식의 세 가지 형태는 다음과 같습니다.There are three forms of new expressions:

  • 개체 생성 식은 클래스 형식 및 값 형식의 새 인스턴스를 만드는 데 사용 됩니다.Object creation expressions are used to create new instances of class types and value types.
  • 배열 생성 식은 배열 형식의 새 인스턴스를 만드는 데 사용 됩니다.Array creation expressions are used to create new instances of array types.
  • 대리자 생성 식은 대리자 형식의 새 인스턴스를 만드는 데 사용 됩니다.Delegate creation expressions are used to create new instances of delegate types.

@No__t-0 연산자는 형식의 인스턴스를 생성 하는 것을 암시 하지만 메모리의 동적 할당을 의미 하는 것은 아닙니다.The new operator implies creation of an instance of a type, but does not necessarily imply dynamic allocation of memory. 특히 값 형식의 인스턴스는 해당 값이 있는 변수 이외에 추가 메모리가 필요 하지 않으며, new을 사용 하 여 값 형식의 인스턴스를 만드는 경우 동적 할당이 발생 하지 않습니다.In particular, instances of value types require no additional memory beyond the variables in which they reside, and no dynamic allocations occur when new is used to create instances of value types.

개체 생성 식Object creation expressions

Object_creation_expressionclass_type 또는 value_type의 새 인스턴스를 만드는 데 사용 됩니다.An object_creation_expression is used to create a new instance of a class_type or a value_type.

object_creation_expression
    : 'new' type '(' argument_list? ')' object_or_collection_initializer?
    | 'new' type object_or_collection_initializer
    ;

object_or_collection_initializer
    : object_initializer
    | collection_initializer
    ;

Object_creation_expression형식은 class_type, value_type 또는 type_parameter여야 합니다.The type of an object_creation_expression must be a class_type, a value_type or a type_parameter. 형식은 abstract class_type수 없습니다.The type cannot be an abstract class_type.

선택적 argument_list (인수 목록)은 형식이 class_type 또는 struct_type경우에만 허용 됩니다.The optional argument_list (Argument lists) is permitted only if the type is a class_type or a struct_type.

개체 생성 식에는 개체 이니셜라이저 또는 컬렉션 이니셜라이저가 포함 된 생성자 인수 목록과 바깥쪽 괄호를 생략할 수 있습니다.An object creation expression can omit the constructor argument list and enclosing parentheses provided it includes an object initializer or collection initializer. 생성자 인수 목록과 바깥쪽 괄호를 생략 하는 것은 빈 인수 목록을 지정 하는 것과 같습니다.Omitting the constructor argument list and enclosing parentheses is equivalent to specifying an empty argument list.

개체 이니셜라이저 또는 컬렉션 이니셜라이저를 포함 하는 개체 생성 식의 처리는 인스턴스 생성자를 먼저 처리 한 다음 개체 이니셜라이저 에 지정 된 멤버 또는 요소 초기화를 처리 하는 것으로 구성 됩니다. 개체 이니셜라이저) 또는 컬렉션 이니셜라이저 (컬렉션 이니셜라이저).Processing of an object creation expression that includes an object initializer or collection initializer consists of first processing the instance constructor and then processing the member or element initializations specified by the object initializer (Object initializers) or collection initializer (Collection initializers).

선택적 argument_list 의 인수에 컴파일 타임 형식 dynamic이 있는 경우 object_creation_expression 는 동적으로 바인딩되고 (동적 바인딩) 런타임에는 런타임에 다음 규칙이 적용 됩니다. 컴파일 시간 형식이 dynamicargument_list 의 해당 인수 형식입니다.If any of the arguments in the optional argument_list has the compile-time type dynamic then the object_creation_expression is dynamically bound (Dynamic binding) and the following rules are applied at run-time using the run-time type of those arguments of the argument_list that have the compile time type dynamic. 그러나 동적 오버 로드 확인의 컴파일 타임 검사에 설명 된 대로 개체 만들기는 제한 된 컴파일 시간 검사를 거칩니다.However, the object creation undergoes a limited compile time check as described in Compile-time checking of dynamic overload resolution.

Object_creation_expression 형식의 @no__t 에 대 한 바인딩 시간 처리 (Tclass_type 또는 value_type 이 고, A는 선택적 argument_list)는 다음 단계로 구성 됩니다.The binding-time processing of an object_creation_expression of the form new T(A), where T is a class_type or a value_type and A is an optional argument_list, consists of the following steps:

  • @No__t-0이 value_type A가 없는 경우:If T is a value_type and A is not present:
    • Object_creation_expression 는 기본 생성자 호출입니다.The object_creation_expression is a default constructor invocation. Object_creation_expression 의 결과는 T 형식의 값 이며,이 값은 system.valuetype 형식에 정의 된 T의 기본값입니다.The result of the object_creation_expression is a value of type T, namely the default value for T as defined in The System.ValueType type.
  • 그렇지 않고 Ttype_parameter A가 없는 경우:Otherwise, if T is a type_parameter and A is not present:
    • @No__t-1에 대해 값 형식 제약 조건 또는 생성자 제약 조건 (형식 매개 변수 제약조건)을 지정 하지 않으면 바인딩 시간 오류가 발생 합니다.If no value type constraint or constructor constraint (Type parameter constraints) has been specified for T, a binding-time error occurs.
    • Object_creation_expression 의 결과는 형식 매개 변수가 바인딩된 런타임 형식의 값입니다. 즉, 해당 형식의 기본 생성자를 호출한 결과입니다.The result of the object_creation_expression is a value of the run-time type that the type parameter has been bound to, namely the result of invoking the default constructor of that type. 런타임 형식은 참조 형식 또는 값 형식일 수 있습니다.The run-time type may be a reference type or a value type.
  • 그렇지 않고 Tclass_type 또는 struct_type인 경우:Otherwise, if T is a class_type or a struct_type:
    • @No__t-0이 abstract class_type경우 컴파일 타임 오류가 발생 합니다.If T is an abstract class_type, a compile-time error occurs.
    • 호출할 인스턴스 생성자는 오버 로드 확인의 오버로드 확인 규칙을 사용 하 여 결정 됩니다.The instance constructor to invoke is determined using the overload resolution rules of Overload resolution. 후보 인스턴스 생성자 집합은 T에 선언 된 모든 액세스 가능한 인스턴스 생성자로 구성 됩니다 .이 생성자는 A (적용 가능한 함수 멤버)에 적용 됩니다.The set of candidate instance constructors consists of all accessible instance constructors declared in T which are applicable with respect to A (Applicable function member). 후보 인스턴스 생성자 집합이 비어 있거나 단일 최상의 인스턴스 생성자를 식별할 수 없는 경우 바인딩 시간 오류가 발생 합니다.If the set of candidate instance constructors is empty, or if a single best instance constructor cannot be identified, a binding-time error occurs.
    • Object_creation_expression 의 결과는-1 @no__t 형식의 값입니다. 즉, 위의 단계에서 결정 한 인스턴스 생성자를 호출 하 여 생성 된 값입니다.The result of the object_creation_expression is a value of type T, namely the value produced by invoking the instance constructor determined in the step above.
  • 그렇지 않으면 object_creation_expression 는 유효 하지 않으며 바인딩 시간 오류가 발생 합니다.Otherwise, the object_creation_expression is invalid, and a binding-time error occurs.

Object_creation_expression 동적으로 바인딩되는 경우에도 컴파일 타임 형식은 여전히 T입니다.Even if the object_creation_expression is dynamically bound, the compile-time type is still T.

@No__t-1 형식의 object_creation_expression 에 대 한 런타임 처리 (Tclass_type 또는 struct_type 이 고, A가 선택적 argument_list인 경우 다음 단계로 구성 됩니다.The run-time processing of an object_creation_expression of the form new T(A), where T is class_type or a struct_type and A is an optional argument_list, consists of the following steps:

  • @No__t-0이 class_type경우:If T is a class_type:
    • @No__t-0 클래스의 새 인스턴스가 할당 됩니다.A new instance of class T is allocated. 새 인스턴스를 할당 하는 데 사용할 수 있는 메모리가 부족 한 경우에는 System.OutOfMemoryException이 throw 되며 추가 단계가 실행 되지 않습니다.If there is not enough memory available to allocate the new instance, a System.OutOfMemoryException is thrown and no further steps are executed.
    • 새 인스턴스의 모든 필드는 해당 기본값으로 초기화 됩니다 (기본값).All fields of the new instance are initialized to their default values (Default values).
    • 인스턴스 생성자는 함수 멤버 호출의 규칙에 따라 호출 됩니다 (동적 오버 로드 확인의 컴파일 시간 검사).The instance constructor is invoked according to the rules of function member invocation (Compile-time checking of dynamic overload resolution). 새로 할당 된 인스턴스에 대 한 참조는 자동으로 인스턴스 생성자에 전달 되 고 해당 생성자 내에서 this으로 인스턴스를 액세스할 수 있습니다.A reference to the newly allocated instance is automatically passed to the instance constructor and the instance can be accessed from within that constructor as this.
  • @No__t-0이 struct_type경우:If T is a struct_type:
    • 임시 지역 변수를 할당 하 여 T 유형의 인스턴스를 만듭니다.An instance of type T is created by allocating a temporary local variable. Struct_type 의 인스턴스 생성자는 생성 되는 인스턴스의 각 필드에 값을 명확 하 게 할당 하는 데 필요 하므로 임시 변수를 초기화 하지 않아도 됩니다.Since an instance constructor of a struct_type is required to definitely assign a value to each field of the instance being created, no initialization of the temporary variable is necessary.
    • 인스턴스 생성자는 함수 멤버 호출의 규칙에 따라 호출 됩니다 (동적 오버 로드 확인의 컴파일 시간 검사).The instance constructor is invoked according to the rules of function member invocation (Compile-time checking of dynamic overload resolution). 새로 할당 된 인스턴스에 대 한 참조는 자동으로 인스턴스 생성자에 전달 되 고 해당 생성자 내에서 this으로 인스턴스를 액세스할 수 있습니다.A reference to the newly allocated instance is automatically passed to the instance constructor and the instance can be accessed from within that constructor as this.

개체 이니셜라이저Object initializers

개체 이니셜라이저 는 0 개 이상의 필드, 속성 또는 개체의 인덱싱된 요소에 대 한 값을 지정 합니다.An object initializer specifies values for zero or more fields, properties or indexed elements of an object.

object_initializer
    : '{' member_initializer_list? '}'
    | '{' member_initializer_list ',' '}'
    ;

member_initializer_list
    : member_initializer (',' member_initializer)*
    ;

member_initializer
    : initializer_target '=' initializer_value
    ;

initializer_target
    : identifier
    | '[' argument_list ']'
    ;

initializer_value
    : expression
    | object_or_collection_initializer
    ;

개체 이니셜라이저는 {} 토큰으로 묶여 있으며 쉼표로 구분 된 멤버 이니셜라이저의 시퀀스로 구성 됩니다.An object initializer consists of a sequence of member initializers, enclosed by { and } tokens and separated by commas. member_initializer 는 초기화에 대 한 대상을 지정 합니다.Each member_initializer designates a target for the initialization. 식별자 는 초기화 되는 개체의 액세스 가능 필드 또는 속성의 이름을 지정 해야 합니다. 반면 대괄호로 묶인 argument_list 는 초기화 되는 개체에 대 한 액세스 가능한 인덱서의 인수를 지정 해야 합니다.An identifier must name an accessible field or property of the object being initialized, whereas an argument_list enclosed in square brackets must specify arguments for an accessible indexer on the object being initialized. 개체 이니셜라이저가 동일한 필드나 속성에 대해 둘 이상의 멤버 이니셜라이저를 포함 하는 것은 오류입니다.It is an error for an object initializer to include more than one member initializer for the same field or property.

initializer_target 뒤에는 등호와 식, 개체 이니셜라이저 또는 컬렉션 이니셜라이저가 있습니다.Each initializer_target is followed by an equals sign and either an expression, an object initializer or a collection initializer. 개체 이니셜라이저 내 식이 초기화 중인 새로 만든 개체를 참조 하는 것은 불가능 합니다.It is not possible for expressions within the object initializer to refer to the newly created object it is initializing.

등호 다음에 식을 지정 하는 멤버 이니셜라이저는 대상에 할당 (단순 할당) 하는 것과 동일한 방식으로 처리 됩니다.A member initializer that specifies an expression after the equals sign is processed in the same way as an assignment (Simple assignment) to the target.

등호 뒤에 개체 이니셜라이저를 지정 하는 멤버 이니셜라이저는 중첩 된 개체 이니셜라이저(예: 포함 된 개체의 초기화)입니다.A member initializer that specifies an object initializer after the equals sign is a nested object initializer, i.e. an initialization of an embedded object. 필드 또는 속성에 새 값을 할당 하는 대신 중첩 된 개체 이니셜라이저의 할당은 필드 또는 속성 멤버에 대 한 할당으로 처리 됩니다.Instead of assigning a new value to the field or property, the assignments in the nested object initializer are treated as assignments to members of the field or property. 중첩 된 개체 이니셜라이저는 값 형식이 인 속성 또는 값 형식이 인 읽기 전용 필드에 적용할 수 없습니다.Nested object initializers cannot be applied to properties with a value type, or to read-only fields with a value type.

등호 뒤에 컬렉션 이니셜라이저를 지정 하는 멤버 이니셜라이저는 포함 된 컬렉션을 초기화 합니다.A member initializer that specifies a collection initializer after the equals sign is an initialization of an embedded collection. 대상 필드, 속성 또는 인덱서에 새 컬렉션을 할당 하는 대신 이니셜라이저에 지정 된 요소가 대상에서 참조 하는 컬렉션에 추가 됩니다.Instead of assigning a new collection to the target field, property or indexer, the elements given in the initializer are added to the collection referenced by the target. 대상은 컬렉션 이니셜라이저에 지정 된 요구 사항을 충족 하는 컬렉션 형식 이어야 합니다.The target must be of a collection type that satisfies the requirements specified in Collection initializers.

인덱스 이니셜라이저에 대 한 인수는 항상 정확히 한 번만 평가 됩니다.The arguments to an index initializer will always be evaluated exactly once. 따라서 인수 끝을 사용 하지 않는 경우 (예: 빈 중첩 된 이니셜라이저가 있으므로) 의도 하지 않은 결과에 대해 계산 됩니다.Thus, even if the arguments end up never getting used (e.g. because of an empty nested initializer), they will be evaluated for their side effects.

다음 클래스는 두 좌표가 있는 점을 나타냅니다.The following class represents a point with two coordinates:

public class Point
{
    int x, y;

    public int X { get { return x; } set { x = value; } }
    public int Y { get { return y; } set { y = value; } }
}

다음과 같이 Point의 인스턴스를 만들고 초기화할 수 있습니다.An instance of Point can be created and initialized as follows:

Point a = new Point { X = 0, Y = 1 };

와 동일한 효과가 있는which has the same effect as

Point __a = new Point();
__a.X = 0;
__a.Y = 1; 
Point a = __a;

여기서 __a은 보이지 않으며 액세스할 수 없는 임시 변수입니다.where __a is an otherwise invisible and inaccessible temporary variable. 다음 클래스는 두 개의 점에서 만든 사각형을 나타냅니다.The following class represents a rectangle created from two points:

public class Rectangle
{
    Point p1, p2;

    public Point P1 { get { return p1; } set { p1 = value; } }
    public Point P2 { get { return p2; } set { p2 = value; } }
}

다음과 같이 Rectangle의 인스턴스를 만들고 초기화할 수 있습니다.An instance of Rectangle can be created and initialized as follows:

Rectangle r = new Rectangle {
    P1 = new Point { X = 0, Y = 1 },
    P2 = new Point { X = 2, Y = 3 }
};

와 동일한 효과가 있는which has the same effect as

Rectangle __r = new Rectangle();
Point __p1 = new Point();
__p1.X = 0;
__p1.Y = 1;
__r.P1 = __p1;
Point __p2 = new Point();
__p2.X = 2;
__p2.Y = 3;
__r.P2 = __p2; 
Rectangle r = __r;

여기서 __r, __p1__p2는 숨겨진 변수 이며 그렇지 않은 경우에는 액세스할 수 없습니다.where __r, __p1 and __p2 are temporary variables that are otherwise invisible and inaccessible.

@No__t-0의 생성자가 두 개의 포함 된 @no__t 인스턴스를 할당 하는 경우If Rectangle's constructor allocates the two embedded Point instances

public class Rectangle
{
    Point p1 = new Point();
    Point p2 = new Point();

    public Point P1 { get { return p1; } }
    public Point P2 { get { return p2; } }
}

다음 구문을 사용 하 여 새 인스턴스를 할당 하는 대신 포함 된 Point 인스턴스를 초기화할 수 있습니다.the following construct can be used to initialize the embedded Point instances instead of assigning new instances:

Rectangle r = new Rectangle {
    P1 = { X = 0, Y = 1 },
    P2 = { X = 2, Y = 3 }
};

와 동일한 효과가 있는which has the same effect as

Rectangle __r = new Rectangle();
__r.P1.X = 0;
__r.P1.Y = 1;
__r.P2.X = 2;
__r.P2.Y = 3;
Rectangle r = __r;

C에 대 한 적절 한 정의가 제공 되는 경우 다음 예제를 제공 합니다.Given an appropriate definition of C, the following example:

var c = new C {
    x = true,
    y = { a = "Hello" },
    z = { 1, 2, 3 },
    ["x"] = 5,
    [0,0] = { "a", "b" },
    [1,2] = {}
};

는 다음과 같은 일련의 할당에 해당 합니다.is equivalent to this series of assignments:

C __c = new C();
__c.x = true;
__c.y.a = "Hello";
__c.z.Add(1); 
__c.z.Add(2);
__c.z.Add(3);
string __i1 = "x";
__c[__i1] = 5;
int __i2 = 0, __i3 = 0;
__c[__i2,__i3].Add("a");
__c[__i2,__i3].Add("b");
int __i4 = 1, __i5 = 2;
var c = __c;

여기서 __c, 등은 표시 되지 않고 소스 코드에 액세스할 수 없는 변수를 생성 합니다.where __c, etc., are generated variables that are invisible and inaccessible to the source code. @No__t-0에 대 한 인수는 한 번만 계산 되며 [1,2]에 대 한 인수는 사용 되지 않은 경우에도 한 번만 평가 됩니다.Note that the arguments for [0,0] are evaluated only once, and the arguments for [1,2] are evaluated once even though they are never used.

컬렉션 이니셜라이저Collection initializers

컬렉션 이니셜라이저는 컬렉션의 요소를 지정 합니다.A collection initializer specifies the elements of a collection.

collection_initializer
    : '{' element_initializer_list '}'
    | '{' element_initializer_list ',' '}'
    ;

element_initializer_list
    : element_initializer (',' element_initializer)*
    ;

element_initializer
    : non_assignment_expression
    | '{' expression_list '}'
    ;

expression_list
    : expression (',' expression)*
    ;

컬렉션 이니셜라이저는 요소 이니셜라이저의 시퀀스로 구성 되며, {} 토큰으로 묶여 있으며 쉼표로 구분 됩니다.A collection initializer consists of a sequence of element initializers, enclosed by { and } tokens and separated by commas. 각 요소 이니셜라이저는 초기화 되는 컬렉션 개체에 추가할 요소를 지정 하 고 {} 토큰으로 묶고 쉼표로 구분 된 식의 목록으로 구성 됩니다.Each element initializer specifies an element to be added to the collection object being initialized, and consists of a list of expressions enclosed by { and } tokens and separated by commas. 단일 식 요소 이니셜라이저는 중괄호 없이 작성 될 수 있지만 멤버 이니셜라이저가 모호성을 방지 하기 위해 할당 식일 수는 없습니다.A single-expression element initializer can be written without braces, but cannot then be an assignment expression, to avoid ambiguity with member initializers. Non_assignment_expression 프로덕션은 에 정의 되어 있습니다.The non_assignment_expression production is defined in Expression.

컬렉션 이니셜라이저를 포함 하는 개체 생성 식의 예는 다음과 같습니다.The following is an example of an object creation expression that includes a collection initializer:

List<int> digits = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

컬렉션 이니셜라이저가 적용 되는 컬렉션 개체는 System.Collections.IEnumerable을 구현 하는 형식 이거나 컴파일 시간 오류가 발생 합니다.The collection object to which a collection initializer is applied must be of a type that implements System.Collections.IEnumerable or a compile-time error occurs. 지정 된 각 요소에 대해 컬렉션 이니셜라이저는 인수 목록으로 요소 이니셜라이저의 식 목록을 사용 하 여 대상 개체의 Add 메서드를 호출 하 고 각 호출에 대해 일반적인 멤버 조회 및 오버 로드 확인을 적용 합니다.For each specified element in order, the collection initializer invokes an Add method on the target object with the expression list of the element initializer as argument list, applying normal member lookup and overload resolution for each invocation. 따라서 컬렉션 개체는 각 요소 이니셜라이저에 대해 이름이 Add 인 해당 인스턴스 또는 확장 메서드를 포함 해야 합니다.Thus, the collection object must have an applicable instance or extension method with the name Add for each element initializer.

다음 클래스는 이름 및 전화 번호 목록이 포함 된 연락처를 나타냅니다.The following class represents a contact with a name and a list of phone numbers:

public class Contact
{
    string name;
    List<string> phoneNumbers = new List<string>();

    public string Name { get { return name; } set { name = value; } }

    public List<string> PhoneNumbers { get { return phoneNumbers; } }
}

@No__t-0은 다음과 같이 만들고 초기화할 수 있습니다.A List<Contact> can be created and initialized as follows:

var contacts = new List<Contact> {
    new Contact {
        Name = "Chris Smith",
        PhoneNumbers = { "206-555-0101", "425-882-8080" }
    },
    new Contact {
        Name = "Bob Harris",
        PhoneNumbers = { "650-555-0199" }
    }
};

와 동일한 효과가 있는which has the same effect as

var __clist = new List<Contact>();
Contact __c1 = new Contact();
__c1.Name = "Chris Smith";
__c1.PhoneNumbers.Add("206-555-0101");
__c1.PhoneNumbers.Add("425-882-8080");
__clist.Add(__c1);
Contact __c2 = new Contact();
__c2.Name = "Bob Harris";
__c2.PhoneNumbers.Add("650-555-0199");
__clist.Add(__c2);
var contacts = __clist;

여기서 __clist, __c1__c2는 숨겨진 변수 이며 그렇지 않은 경우에는 액세스할 수 없습니다.where __clist, __c1 and __c2 are temporary variables that are otherwise invisible and inaccessible.

배열 만들기 식Array creation expressions

Array_creation_expressionarray_type의 새 인스턴스를 만드는 데 사용 됩니다.An array_creation_expression is used to create a new instance of an array_type.

array_creation_expression
    : 'new' non_array_type '[' expression_list ']' rank_specifier* array_initializer?
    | 'new' array_type array_initializer
    | 'new' rank_specifier array_initializer
    ;

첫 번째 폼의 배열 생성 식은 식 목록에서 각 개별 식을 삭제 하 여 생성 되는 형식의 배열 인스턴스를 할당 합니다.An array creation expression of the first form allocates an array instance of the type that results from deleting each of the individual expressions from the expression list. 예를 들어 배열 생성 식 new int[10,20]int[,] 형식의 배열 인스턴스를 생성 하 고, 배열 생성 식 new int[10][,]는-3 @no__t 형식의 배열을 생성 합니다.For example, the array creation expression new int[10,20] produces an array instance of type int[,], and the array creation expression new int[10][,] produces an array of type int[][,]. 식 목록의 각 식은 int, uint, long 또는 ulong 형식 이거나 이러한 형식 중 하나 이상으로 암시적으로 변환할 수 있어야 합니다.Each expression in the expression list must be of type int, uint, long, or ulong, or implicitly convertible to one or more of these types. 각 식의 값은 새로 할당 된 배열 인스턴스에서 해당 차원의 길이를 결정 합니다.The value of each expression determines the length of the corresponding dimension in the newly allocated array instance. 배열 차원의 길이는 음수가 아니어야 하므로 식 목록에 음수 값을 가진 constant_expression 을 포함 하는 컴파일 시간 오류가 발생 합니다.Since the length of an array dimension must be nonnegative, it is a compile-time error to have a constant_expression with a negative value in the expression list.

안전 하지 않은 컨텍스트 (안전 하지않은 컨텍스트)를 제외 하 고 배열의 레이아웃은 지정 되지 않습니다.Except in an unsafe context (Unsafe contexts), the layout of arrays is unspecified.

첫 번째 폼의 배열 생성 식에 배열 이니셜라이저가 포함 된 경우 식 목록의 각 식은 상수 여야 하며 식 목록에 지정 된 차수 및 차원 길이는 배열 이니셜라이저의 차수와 일치 해야 합니다.If an array creation expression of the first form includes an array initializer, each expression in the expression list must be a constant and the rank and dimension lengths specified by the expression list must match those of the array initializer.

두 번째 또는 세 번째 형식의 배열 생성 식에서 지정 된 배열 형식 또는 차수 지정자의 순위는 배열 이니셜라이저의 차수와 일치 해야 합니다.In an array creation expression of the second or third form, the rank of the specified array type or rank specifier must match that of the array initializer. 개별 차원 길이는 배열 이니셜라이저의 해당 하는 각 중첩 수준에 있는 요소 수에서 유추 됩니다.The individual dimension lengths are inferred from the number of elements in each of the corresponding nesting levels of the array initializer. 따라서 식은Thus, the expression

new int[,] {{0, 1}, {2, 3}, {4, 5}}

정확히 일치exactly corresponds to

new int[3, 2] {{0, 1}, {2, 3}, {4, 5}}

세 번째 형식의 배열 생성 식은 암시적으로 형식화 된 배열 생성 식이라고 합니다.An array creation expression of the third form is referred to as an implicitly typed array creation expression. 배열의 요소 형식은 명시적으로 지정 되지 않지만 배열 이니셜라이저의 식 집합에서 가장 적합 한 공통 형식 (식 집합의 가장 일반적인 형식)으로 결정 된다는 점을 제외 하 고는 두 번째 형식과 비슷합니다.It is similar to the second form, except that the element type of the array is not explicitly given, but determined as the best common type (Finding the best common type of a set of expressions) of the set of expressions in the array initializer. 다차원 배열의 경우 즉, rank_specifier 에 하나 이상의 쉼표가 포함 된 경우이 집합은 nested array_initializers에 있는 모든 으로 구성 됩니다.For a multidimensional array, i.e., one where the rank_specifier contains at least one comma, this set comprises all expressions found in nested array_initializers.

배열 이니셜라이저는 배열 이니셜라이저에 자세히 설명 되어 있습니다.Array initializers are described further in Array initializers.

배열 생성 식의 평가 결과는 값으로 분류 됩니다. 즉, 새로 할당 된 배열 인스턴스에 대 한 참조입니다.The result of evaluating an array creation expression is classified as a value, namely a reference to the newly allocated array instance. 배열 생성 식의 런타임 처리는 다음 단계로 구성 됩니다.The run-time processing of an array creation expression consists of the following steps:

  • Expression_list 의 차원 길이 식은 순서 대로 왼쪽에서 오른쪽으로 계산 됩니다.The dimension length expressions of the expression_list are evaluated in order, from left to right. 각 식을 계산 하 고 다음 형식 중 하나로 암시적 변환 (암시적변환)을 수행 합니다. int, uint, long, ulongFollowing evaluation of each expression, an implicit conversion (Implicit conversions) to one of the following types is performed: int, uint, long, ulong. 이 목록에서 암시적 변환이 있는 첫 번째 형식이 선택 됩니다.The first type in this list for which an implicit conversion exists is chosen. 식의 계산 또는 후속 암시적 변환으로 인해 예외가 발생 하면 더 이상 식이 계산 되지 않고 추가 단계가 실행 되지 않습니다.If evaluation of an expression or the subsequent implicit conversion causes an exception, then no further expressions are evaluated and no further steps are executed.
  • 차원 길이의 계산 된 값은 다음과 같이 유효성이 검사 됩니다.The computed values for the dimension lengths are validated as follows. 하나 이상의 값이 0 보다 작은 경우 System.OverflowException이 throw 되 고 추가 단계가 실행 되지 않습니다.If one or more of the values are less than zero, a System.OverflowException is thrown and no further steps are executed.
  • 지정 된 차원 길이의 배열 인스턴스가 할당 됩니다.An array instance with the given dimension lengths is allocated. 새 인스턴스를 할당 하는 데 사용할 수 있는 메모리가 부족 한 경우에는 System.OutOfMemoryException이 throw 되며 추가 단계가 실행 되지 않습니다.If there is not enough memory available to allocate the new instance, a System.OutOfMemoryException is thrown and no further steps are executed.
  • 새 배열 인스턴스의 모든 요소는 기본값으로 초기화 됩니다 (기본값).All elements of the new array instance are initialized to their default values (Default values).
  • 배열 생성 식에 배열 이니셜라이저가 포함 된 경우 배열 이니셜라이저의 각 식이 계산 되어 해당 배열 요소에 할당 됩니다.If the array creation expression contains an array initializer, then each expression in the array initializer is evaluated and assigned to its corresponding array element. 평가 및 할당은 배열 이니셜라이저로 식이 작성 된 순서 대로 수행 됩니다. 즉, 요소는 인덱스 순서에 따라 초기화 되며 가장 오른쪽 차원이 먼저 늘어납니다.The evaluations and assignments are performed in the order the expressions are written in the array initializer—in other words, elements are initialized in increasing index order, with the rightmost dimension increasing first. 지정 된 식 또는 해당 배열 요소에 대 한 후속 할당의 평가로 인해 예외가 발생 하는 경우에는 더 이상 요소가 초기화 되지 않으며 나머지 요소는 기본값을 갖습니다.If evaluation of a given expression or the subsequent assignment to the corresponding array element causes an exception, then no further elements are initialized (and the remaining elements will thus have their default values).

배열 생성 식은 배열 형식의 요소를 포함 하는 배열을 인스턴스화할 수 있지만 이러한 배열의 요소를 수동으로 초기화 해야 합니다.An array creation expression permits instantiation of an array with elements of an array type, but the elements of such an array must be manually initialized. 예를 들어, 다음 문For example, the statement

int[][] a = new int[100][];

int[] 형식의 100 요소를 사용 하 여 1 차원 배열을 만듭니다.creates a single-dimensional array with 100 elements of type int[]. 각 요소의 초기 값은 null입니다.The initial value of each element is null. 동일한 배열 생성 식 에서도 하위 배열과 문을 인스턴스화할 수는 없습니다.It is not possible for the same array creation expression to also instantiate the sub-arrays, and the statement

int[][] a = new int[100][5];        // Error

컴파일 시간 오류가 발생 합니다.results in a compile-time error. 대신 하위 배열의 인스턴스화를 수동으로 수행 해야 합니다.Instantiation of the sub-arrays must instead be performed manually, as in

int[][] a = new int[100][];
for (int i = 0; i < 100; i++) a[i] = new int[5];

배열의 배열에 "사각형" 모양이 있는 경우 즉, 하위 배열의 길이가 모두 같은 경우에는 다차원 배열을 사용 하는 것이 더 효율적입니다.When an array of arrays has a "rectangular" shape, that is when the sub-arrays are all of the same length, it is more efficient to use a multi-dimensional array. 위의 예제에서 배열의 배열을 인스턴스화하면 101 개체가 생성 됩니다 (하나의 외부 배열 및 100 하위 배열).In the example above, instantiation of the array of arrays creates 101 objects—one outer array and 100 sub-arrays. 반면,In contrast,

int[,] = new int[100, 5];

단일 개체와 2 차원 배열을 만들고 단일 문에서 할당을 수행 합니다.creates only a single object, a two-dimensional array, and accomplishes the allocation in a single statement.

다음은 암시적으로 형식화 된 배열 생성 식의 예입니다.The following are examples of implicitly typed array creation expressions:

var a = new[] { 1, 10, 100, 1000 };                       // int[]

var b = new[] { 1, 1.5, 2, 2.5 };                         // double[]

var c = new[,] { { "hello", null }, { "world", "!" } };   // string[,]

var d = new[] { 1, "one", 2, "two" };                     // Error

@No__t-0 또는 string은 암시적으로 다른 형식으로 변환할 수 없으므로 마지막 식에서 컴파일 시간 오류가 발생 합니다.The last expression causes a compile-time error because neither int nor string is implicitly convertible to the other, and so there is no best common type. 이 경우 명시적으로 형식화 된 배열 생성 식을 사용 해야 합니다. 예를 들어, @no__t 하는 형식을 지정 합니다.An explicitly typed array creation expression must be used in this case, for example specifying the type to be object[]. 또는 요소 중 하나를 공통 기본 형식으로 캐스팅 한 다음 유추 된 요소 형식이 될 수 있습니다.Alternatively, one of the elements can be cast to a common base type, which would then become the inferred element type.

암시적으로 형식화 된 배열 생성 식은 익명 개체 이니셜라이저 (익명 개체 생성 식)와 결합 하 여 익명으로 형식화 된 데이터 구조를 만들 수 있습니다.Implicitly typed array creation expressions can be combined with anonymous object initializers (Anonymous object creation expressions) to create anonymously typed data structures. 예를 들어 다음과 같은 가치를 제공해야 합니다.For example:

var contacts = new[] {
    new {
        Name = "Chris Smith",
        PhoneNumbers = new[] { "206-555-0101", "425-882-8080" }
    },
    new {
        Name = "Bob Harris",
        PhoneNumbers = new[] { "650-555-0199" }
    }
};

대리자 생성 식Delegate creation expressions

Delegate_creation_expressiondelegate_type의 새 인스턴스를 만드는 데 사용 됩니다.A delegate_creation_expression is used to create a new instance of a delegate_type.

delegate_creation_expression
    : 'new' delegate_type '(' expression ')'
    ;

대리자 생성 식의 인수는 메서드 그룹, 익명 함수 또는 컴파일 시간 형식의 값 dynamic 또는 delegate_type이어야 합니다.The argument of a delegate creation expression must be a method group, an anonymous function or a value of either the compile time type dynamic or a delegate_type. 인수가 메서드 그룹인 경우 메서드를 식별 하 고, 인스턴스 메서드의 경우 대리자를 만들 개체를 식별 합니다.If the argument is a method group, it identifies the method and, for an instance method, the object for which to create a delegate. 인수가 익명 함수 이면 대리자 대상의 매개 변수 및 메서드 본문을 직접 정의 합니다.If the argument is an anonymous function it directly defines the parameters and method body of the delegate target. 인수가 값 이면 복사본을 만들 대리자 인스턴스를 식별 합니다.If the argument is a value it identifies a delegate instance of which to create a copy.

의 컴파일 시간 형식이-1 @no__t 경우 delegate_creation_expression 는 동적으로 바인딩되고 (동적 바인딩) 아래 규칙은 의 런타임 형식을 사용 하 여 런타임에 적용 됩니다.If the expression has the compile-time type dynamic, the delegate_creation_expression is dynamically bound (Dynamic binding), and the rules below are applied at run-time using the run-time type of the expression. 그렇지 않으면 규칙이 컴파일 타임에 적용 됩니다.Otherwise the rules are applied at compile-time.

@No__t-1 형식의 delegate_creation_expression 에 대 한 바인딩 시간 처리 (Ddelegate_type 이 고, E)는 다음 단계로 구성 됩니다.The binding-time processing of a delegate_creation_expression of the form new D(E), where D is a delegate_type and E is an expression, consists of the following steps:

  • @No__t-0이 메서드 그룹인 경우 대리자 생성 식은 E에서 D으로 메서드 그룹 변환 (메서드 그룹변환)과 동일한 방식으로 처리 됩니다.If E is a method group, the delegate creation expression is processed in the same way as a method group conversion (Method group conversions) from E to D.
  • @No__t-0이 익명 함수 이면 대리자 생성 식은 E에서 D으로의 익명 함수 변환 (익명 함수변환)과 동일한 방식으로 처리 됩니다.If E is an anonymous function, the delegate creation expression is processed in the same way as an anonymous function conversion (Anonymous function conversions) from E to D.
  • @No__t-0이 값 인 경우 ED과 호환 되는 (대리자 선언) 호환 되어야 하며, 결과는 E와 동일한 호출 목록을 참조 하는 D 형식의 새로 생성 된 대리자에 대 한 참조입니다.If E is a value, E must be compatible (Delegate declarations) with D, and the result is a reference to a newly created delegate of type D that refers to the same invocation list as E. @No__t-0이 D과 호환 되지 않으면 컴파일 시간 오류가 발생 합니다.If E is not compatible with D, a compile-time error occurs.

@No__t-1 형식의 delegate_creation_expression 에 대 한 런타임 처리 (Ddelegate_type 이 고, E)는 다음 단계로 구성 됩니다.The run-time processing of a delegate_creation_expression of the form new D(E), where D is a delegate_type and E is an expression, consists of the following steps:

  • @No__t-0이 메서드 그룹인 경우 대리자 생성 식은 E에서 D으로 메서드 그룹 변환 (메서드 그룹변환)으로 평가 됩니다.If E is a method group, the delegate creation expression is evaluated as a method group conversion (Method group conversions) from E to D.
  • @No__t-0이 익명 함수 이면 대리자 생성은 E에서 D (익명 함수 변환)로의 익명 함수 변환으로 평가 됩니다.If E is an anonymous function, the delegate creation is evaluated as an anonymous function conversion from E to D (Anonymous function conversions).
  • @No__t-0은 delegate_type값입니다.If E is a value of a delegate_type:
    • E이 계산 됩니다.E is evaluated. 이 평가에서 예외가 발생 하면 추가 단계가 실행 되지 않습니다.If this evaluation causes an exception, no further steps are executed.
    • @No__t-0의 값이-1 @no__t 이면 System.NullReferenceException가 throw 되며 추가 단계가 실행 되지 않습니다.If the value of E is null, a System.NullReferenceException is thrown and no further steps are executed.
    • 대리자 형식의 새 인스턴스 D이 할당 됩니다.A new instance of the delegate type D is allocated. 새 인스턴스를 할당 하는 데 사용할 수 있는 메모리가 부족 한 경우에는 System.OutOfMemoryException이 throw 되며 추가 단계가 실행 되지 않습니다.If there is not enough memory available to allocate the new instance, a System.OutOfMemoryException is thrown and no further steps are executed.
    • 새 대리자 인스턴스는 E에 지정 된 대리자 인스턴스와 동일한 호출 목록으로 초기화 됩니다.The new delegate instance is initialized with the same invocation list as the delegate instance given by E.

대리자의 호출 목록은 대리자를 인스턴스화할 때 결정 되며 대리자의 전체 수명 동안 일정 하 게 유지 됩니다.The invocation list of a delegate is determined when the delegate is instantiated and then remains constant for the entire lifetime of the delegate. 즉, 대리자를 만든 후에는 대리자의 대상 호출 가능 엔터티를 변경할 수 없습니다.In other words, it is not possible to change the target callable entities of a delegate once it has been created. 두 대리자를 결합 하거나 하나를 다른 (대리자 선언)에서 제거 하면 새 대리자 결과가 반환 됩니다. 기존 대리자의 내용이 변경 되지 않았습니다.When two delegates are combined or one is removed from another (Delegate declarations), a new delegate results; no existing delegate has its contents changed.

속성, 인덱서, 사용자 정의 연산자, 인스턴스 생성자, 소멸자 또는 정적 생성자를 참조 하는 대리자를 만들 수는 없습니다.It is not possible to create a delegate that refers to a property, indexer, user-defined operator, instance constructor, destructor, or static constructor.

위에서 설명한 것 처럼 메서드 그룹에서 대리자를 만들면 대리자의 형식 매개 변수 목록 및 반환 형식에 따라 오버 로드 된 메서드 중에서 선택할 메서드를 결정 합니다.As described above, when a delegate is created from a method group, the formal parameter list and return type of the delegate determine which of the overloaded methods to select. 예제에서In the example

delegate double DoubleFunc(double x);

class A
{
    DoubleFunc f = new DoubleFunc(Square);

    static float Square(float x) {
        return x * x;
    }

    static double Square(double x) {
        return x * x;
    }
}

A.f 필드는 두 번째 Square 메서드를 참조 하는 대리자를 사용 하 여 초기화 됩니다. 해당 메서드는 DoubleFunc의 형식 매개 변수 목록 및 반환 형식과 정확히 일치 하기 때문입니다.the A.f field is initialized with a delegate that refers to the second Square method because that method exactly matches the formal parameter list and return type of DoubleFunc. 두 번째 Square 메서드가 없는 경우 컴파일 타임 오류가 발생 합니다.Had the second Square method not been present, a compile-time error would have occurred.

익명 개체 생성 식Anonymous object creation expressions

Anonymous_object_creation_expression 는 익명 형식의 개체를 만드는 데 사용 됩니다.An anonymous_object_creation_expression is used to create an object of an anonymous type.

anonymous_object_creation_expression
    : 'new' anonymous_object_initializer
    ;

anonymous_object_initializer
    : '{' member_declarator_list? '}'
    | '{' member_declarator_list ',' '}'
    ;

member_declarator_list
    : member_declarator (',' member_declarator)*
    ;

member_declarator
    : simple_name
    | member_access
    | base_access
    | null_conditional_member_access
    | identifier '=' expression
    ;

익명 개체 이니셜라이저는 무명 형식을 선언 하 고 해당 형식의 인스턴스를 반환 합니다.An anonymous object initializer declares an anonymous type and returns an instance of that type. 익명 형식은 object에서 직접 상속 되는 이름이 없는 클래스 형식입니다.An anonymous type is a nameless class type that inherits directly from object. 익명 형식의 멤버는 형식의 인스턴스를 만드는 데 사용 되는 익명 개체 이니셜라이저에서 유추 되는 읽기 전용 속성의 시퀀스입니다.The members of an anonymous type are a sequence of read-only properties inferred from the anonymous object initializer used to create an instance of the type. 특히 폼의 익명 개체 이니셜라이저Specifically, an anonymous object initializer of the form

new { p1 = e1, p2 = e2, ..., pn = en }

폼의 익명 형식을 선언 합니다.declares an anonymous type of the form

class __Anonymous1
{
    private readonly T1 f1;
    private readonly T2 f2;
    ...
    private readonly Tn fn;

    public __Anonymous1(T1 a1, T2 a2, ..., Tn an) {
        f1 = a1;
        f2 = a2;
        ...
        fn = an;
    }

    public T1 p1 { get { return f1; } }
    public T2 p2 { get { return f2; } }
    ...
    public Tn pn { get { return fn; } }

    public override bool Equals(object __o) { ... }
    public override int GetHashCode() { ... }
}

여기서 각 Tx은 해당 하는 식의 형식 ex입니다.where each Tx is the type of the corresponding expression ex. Member_declarator 에 사용 되는 식에는 형식이 있어야 합니다.The expression used in a member_declarator must have a type. 따라서 member_declarator 의 식이 null 또는 익명 함수인 경우 컴파일 타임 오류가 발생 합니다.Thus, it is a compile-time error for an expression in a member_declarator to be null or an anonymous function. 또한 식에 안전 하지 않은 형식이 있는 경우 컴파일 시간 오류가 발생 합니다.It is also a compile-time error for the expression to have an unsafe type.

익명 형식의 이름 및 매개 변수의 @no__t는 컴파일러에서 자동으로 생성 되며 프로그램 텍스트에서 참조할 수 없습니다.The names of an anonymous type and of the parameter to its Equals method are automatically generated by the compiler and cannot be referenced in program text.

동일한 프로그램 내에서 동일한 이름 및 컴파일 시간 형식의 속성 시퀀스를 동일한 순서로 지정 하는 두 개의 익명 개체 이니셜라이저는 동일한 익명 형식의 인스턴스를 생성 합니다.Within the same program, two anonymous object initializers that specify a sequence of properties of the same names and compile-time types in the same order will produce instances of the same anonymous type.

예제에서In the example

var p1 = new { Name = "Lawnmower", Price = 495.00 };
var p2 = new { Name = "Shovel", Price = 26.95 };
p1 = p2;

p1p2이 같은 익명 형식 이므로 마지막 줄에 대 한 할당을 사용할 수 있습니다.the assignment on the last line is permitted because p1 and p2 are of the same anonymous type.

익명 형식의 EqualsGetHashcode 메서드는 object에서 상속 된 메서드를 재정의 하며, 속성의 Equals과 @no__t의 측면에서 정의 되므로 동일한 익명 형식의 두 인스턴스는 해당 속성이 모두 인 경우에만 동일 합니다. 다릅니다.The Equals and GetHashcode methods on anonymous types override the methods inherited from object, and are defined in terms of the Equals and GetHashcode of the properties, so that two instances of the same anonymous type are equal if and only if all their properties are equal.

멤버 선언 자는 단순한 이름 (형식 유추), 멤버 액세스 (동적 오버 로드 확인의 컴파일 타임 확인), 기본 액세스 (기본 액세스) 또는 null 조건부 멤버 액세스 ( Null 조건부 식 (프로젝션 이니셜라이저)A member declarator can be abbreviated to a simple name (Type inference), a member access (Compile-time checking of dynamic overload resolution), a base access (Base access) or a null-conditional member access (Null-conditional expressions as projection initializers). 이를 프로젝션 이니셜라이저 라고 하며 동일한 이름의 속성에 대 한 선언과 할당의 약어입니다.This is called a projection initializer and is shorthand for a declaration of and assignment to a property with the same name. 특히, 형식의 멤버 선언 자Specifically, member declarators of the forms

identifier
expr.identifier

는 각각 다음과 정확히 일치 합니다.are precisely equivalent to the following, respectively:

identifier = identifier
identifier = expr.identifier

따라서 프로젝션 이니셜라이저에서 식별자 는 값과 값이 할당 된 필드 또는 속성을 모두 선택 합니다.Thus, in a projection initializer the identifier selects both the value and the field or property to which the value is assigned. 단지 값 뿐만 아니라 값의 이름을 나타내는 프로젝션 이니셜라이저 프로젝트도 직관적입니다.Intuitively, a projection initializer projects not just a value, but also the name of the value.

Typeof 연산자The typeof operator

@No__t-0 연산자는 형식에 대 한 System.Type 개체를 가져오는 데 사용 됩니다.The typeof operator is used to obtain the System.Type object for a type.

typeof_expression
    : 'typeof' '(' type ')'
    | 'typeof' '(' unbound_type_name ')'
    | 'typeof' '(' 'void' ')'
    ;

unbound_type_name
    : identifier generic_dimension_specifier?
    | identifier '::' identifier generic_dimension_specifier?
    | unbound_type_name '.' identifier generic_dimension_specifier?
    ;

generic_dimension_specifier
    : '<' comma* '>'
    ;

comma
    : ','
    ;

Typeof_expression 의 첫 번째 형태는 typeof 키워드와 괄호로 묶은 형식으로 구성 됩니다.The first form of typeof_expression consists of a typeof keyword followed by a parenthesized type. 이 폼의 식 결과는 표시 된 형식에 대 한 System.Type 개체입니다.The result of an expression of this form is the System.Type object for the indicated type. 지정 된 형식에는 @no__t 0 개체가 하나만 있습니다.There is only one System.Type object for any given type. 즉, @ no__t-0 형식의 경우-1 @no__t 항상 true입니다.This means that for a type T, typeof(T) == typeof(T) is always true. 형식은 -1 @no__t 수 없습니다.The type cannot be dynamic.

Typeof_expression 의 두 번째 형태는 typeof 키워드와 괄호로 묶은 unbound_type_name로 구성 됩니다.The second form of typeof_expression consists of a typeof keyword followed by a parenthesized unbound_type_name. Unbound_type_name 에는 type_name (네임 스페이스 및 형식 이름)가 포함 되어 있습니다. 단, unbound_type_name 에는 type_name이 포함 된 generic_dimension_specifiers가 포함 됩니다. argument_lists.An unbound_type_name is very similar to a type_name (Namespace and type names) except that an unbound_type_name contains generic_dimension_specifiers where a type_name contains type_argument_lists. Typeof_expression 의 피연산자가 unbound_type_nametype_name둘 다의 문법을 충족 하는 토큰 시퀀스 이면, generic_dimension_specifier 및 type_argument가 모두 포함 되어 있지 않으면입니다. _list, 토큰 시퀀스는 type_name으로 간주 됩니다.When the operand of a typeof_expression is a sequence of tokens that satisfies the grammars of both unbound_type_name and type_name, namely when it contains neither a generic_dimension_specifier nor a type_argument_list, the sequence of tokens is considered to be a type_name. Unbound_type_name 의 의미는 다음과 같이 결정 됩니다.The meaning of an unbound_type_name is determined as follows:

  • generic_dimension_specifier 를 쉼표 수가 같은 type_argument_list 로 바꾸고 type_name @no__t 키워드를 각 type_argument로 대체 하 여 토큰 시퀀스를 으로 변환 합니다.Convert the sequence of tokens to a type_name by replacing each generic_dimension_specifier with a type_argument_list having the same number of commas and the keyword object as each type_argument.
  • 모든 형식 매개 변수 제약 조건을 무시 하 고 결과 type_name를 평가 합니다.Evaluate the resulting type_name, while ignoring all type parameter constraints.
  • Unbound_type_name 는 생성 된 형식 (바인딩된 형식 및 바인딩되지않은 형식)과 연결 된 바인딩되지 않은 제네릭 형식으로 확인 됩니다.The unbound_type_name resolves to the unbound generic type associated with the resulting constructed type (Bound and unbound types).

Typeof_expression 의 결과는 바인딩되지 않은 결과 제네릭 형식에 대 한 System.Type 개체입니다.The result of the typeof_expression is the System.Type object for the resulting unbound generic type.

Typeof_expression 의 세 번째 형태는 typeof 키워드로 구성 된 후 괄호로 묶은 void 키워드로 구성 됩니다.The third form of typeof_expression consists of a typeof keyword followed by a parenthesized void keyword. 이 폼의 식의 결과는 형식이 없음을 나타내는 0 @no__t 개체입니다.The result of an expression of this form is the System.Type object that represents the absence of a type. @No__t-0에서 반환 된 형식 개체는 모든 형식에 대해 반환 되는 형식 개체와는 다릅니다.The type object returned by typeof(void) is distinct from the type object returned for any type. 이 특수 형식 개체는 언어의 메서드에 대 한 리플렉션을 허용 하는 클래스 라이브러리에서 유용 합니다. 이러한 메서드는 void 메서드를 포함 하 여 모든 메서드의 반환 형식 (System.Type)을 나타내는 방법을 사용 하려고 합니다.This special type object is useful in class libraries that allow reflection onto methods in the language, where those methods wish to have a way to represent the return type of any method, including void methods, with an instance of System.Type.

@No__t-0 연산자는 형식 매개 변수에 사용할 수 있습니다.The typeof operator can be used on a type parameter. 결과는 형식 매개 변수에 바인딩된 런타임 형식에 대 한 @no__t 0 개체입니다.The result is the System.Type object for the run-time type that was bound to the type parameter. @No__t-0 연산자는 생성 된 형식이 나 바인딩되지 않은 제네릭 형식 (바인딩된 및 바인딩되지않은 형식) 에서도 사용할 수 있습니다.The typeof operator can also be used on a constructed type or an unbound generic type (Bound and unbound types). 바인딩되지 않은 제네릭 형식에 대 한 System.Type 개체는 인스턴스 형식의 System.Type 개체와 다릅니다.The System.Type object for an unbound generic type is not the same as the System.Type object of the instance type. 인스턴스 형식은 런타임에 항상 폐쇄형 생성 형식 이므로 System.Type 개체는 사용 중인 런타임 형식 인수에 따라 달라 지지만 바인딩되지 않은 제네릭 형식에는 형식 인수가 없습니다.The instance type is always a closed constructed type at run-time so its System.Type object depends on the run-time type arguments in use, while the unbound generic type has no type arguments.

예제The example

using System;

class X<T>
{
    public static void PrintTypes() {
        Type[] t = {
            typeof(int),
            typeof(System.Int32),
            typeof(string),
            typeof(double[]),
            typeof(void),
            typeof(T),
            typeof(X<T>),
            typeof(X<X<T>>),
            typeof(X<>)
        };
        for (int i = 0; i < t.Length; i++) {
            Console.WriteLine(t[i]);
        }
    }
}

class Test
{
    static void Main() {
        X<int>.PrintTypes();
    }
}

는 다음과 같은 출력을 생성 합니다.produces the following output:

System.Int32
System.Int32
System.String
System.Double[]
System.Void
System.Int32
X`1[System.Int32]
X`1[X`1[System.Int32]]
X`1[T]

@No__t-0과 System.Int32은 같은 형식입니다.Note that int and System.Int32 are the same type.

또한 typeof(X<>)의 결과는 형식 인수에 종속 되지 않지만 typeof(X<T>)의 결과는입니다.Also note that the result of typeof(X<>) does not depend on the type argument but the result of typeof(X<T>) does.

Checked 및 Unchecked 연산자The checked and unchecked operators

@No__t-0 및 unchecked 연산자는 정수 계열 형식 산술 연산 및 변환에 대 한 오버플로 검사 컨텍스트 를 제어 하는 데 사용 됩니다.The checked and unchecked operators are used to control the overflow checking context for integral-type arithmetic operations and conversions.

checked_expression
    : 'checked' '(' expression ')'
    ;

unchecked_expression
    : 'unchecked' '(' expression ')'
    ;

@No__t-0 연산자는 확인 된 컨텍스트에서 포함 된 식을 계산 하 고, unchecked 연산자는 unchecked 컨텍스트에서 포함 된 식을 계산 합니다.The checked operator evaluates the contained expression in a checked context, and the unchecked operator evaluates the contained expression in an unchecked context. Checked_expression 또는 unchecked_expression 는 지정 된 오버플로 검사 컨텍스트에서 포함 된 식이 계산 되는 점을 제외 하 고 parenthesized_expression (괄호로 묶인 식)와 정확히 일치 합니다. .A checked_expression or unchecked_expression corresponds exactly to a parenthesized_expression (Parenthesized expressions), except that the contained expression is evaluated in the given overflow checking context.

@No__t-0 및 unchecked 문 (checked 및 unchecked 문)을 통해 오버플로 검사 컨텍스트를 제어할 수도 있습니다.The overflow checking context can also be controlled through the checked and unchecked statements (The checked and unchecked statements).

다음 작업은 checkedunchecked 연산자 및 문에 의해 설정 된 오버플로 검사 컨텍스트의 영향을 받습니다.The following operations are affected by the overflow checking context established by the checked and unchecked operators and statements:

위의 작업 중 하나가 너무 커서 대상 형식에서 나타낼 수 없는 결과를 생성 하는 경우 작업이 수행 되는 컨텍스트는 결과 동작을 제어 합니다.When one of the above operations produce a result that is too large to represent in the destination type, the context in which the operation is performed controls the resulting behavior:

  • @No__t-0 컨텍스트에서 연산이 상수 식 (상수식) 이면 컴파일 시간 오류가 발생 합니다.In a checked context, if the operation is a constant expression (Constant expressions), a compile-time error occurs. 그렇지 않으면 런타임에 작업이 수행 될 때 System.OverflowException이 throw 됩니다.Otherwise, when the operation is performed at run-time, a System.OverflowException is thrown.
  • @No__t-0 컨텍스트에서는 대상 형식에 맞지 않는 상위 비트를 삭제 하 여 결과를 자릅니다.In an unchecked context, the result is truncated by discarding any high-order bits that do not fit in the destination type.

상수가 아닌 식 (런타임에 계산 되는 식)의 경우 checked 또는 unchecked 연산자나 문으로 묶이지 않은 경우에는 외부 요소 (예: 컴파일러 스위치 및를 제외 하 고 기본 오버플로 검사 컨텍스트는-2 @no__t 실행 환경 구성)을 호출 하 여 @no__t 3 평가를 호출 합니다.For non-constant expressions (expressions that are evaluated at run-time) that are not enclosed by any checked or unchecked operators or statements, the default overflow checking context is unchecked unless external factors (such as compiler switches and execution environment configuration) call for checked evaluation.

상수 식 (컴파일 시간에 완전히 계산 될 수 있는 식)의 경우 기본 오버플로 검사 컨텍스트는 항상 checked입니다.For constant expressions (expressions that can be fully evaluated at compile-time), the default overflow checking context is always checked. 상수 식이 unchecked 컨텍스트에 명시적으로 배치 되지 않는 한 식의 컴파일 타임 계산 중에 발생 하는 오버플로는 항상 컴파일 시간 오류를 발생 시킵니다.Unless a constant expression is explicitly placed in an unchecked context, overflows that occur during the compile-time evaluation of the expression always cause compile-time errors.

익명 함수의 본문은 익명 함수가 발생 하는 checked 또는 unchecked 컨텍스트의 영향을 받지 않습니다.The body of an anonymous function is not affected by checked or unchecked contexts in which the anonymous function occurs.

예제에서In the example

class Test
{
    static readonly int x = 1000000;
    static readonly int y = 1000000;

    static int F() {
        return checked(x * y);      // Throws OverflowException
    }

    static int G() {
        return unchecked(x * y);    // Returns -727379968
    }

    static int H() {
        return x * y;               // Depends on default
    }
}

컴파일 시간에 식을 계산할 수 없기 때문에 컴파일 시간 오류가 보고 되지 않습니다.no compile-time errors are reported since neither of the expressions can be evaluated at compile-time. 런타임에 F 메서드는 System.OverflowException을 throw 하 고, G 메서드는-727379968 (범위를 벗어난 결과의 하위 32 비트)을 반환 합니다.At run-time, the F method throws a System.OverflowException, and the G method returns -727379968 (the lower 32 bits of the out-of-range result). @No__t-0 메서드의 동작은 컴파일의 기본 오버플로 검사 컨텍스트에 따라 달라 지지만 F과 동일 하거나 G와 동일 합니다.The behavior of the H method depends on the default overflow checking context for the compilation, but it is either the same as F or the same as G.

예제에서In the example

class Test
{
    const int x = 1000000;
    const int y = 1000000;

    static int F() {
        return checked(x * y);      // Compile error, overflow
    }

    static int G() {
        return unchecked(x * y);    // Returns -727379968
    }

    static int H() {
        return x * y;               // Compile error, overflow
    }
}

FH의 상수 식을 계산할 때 발생 하는 오버플로는 식이 checked 컨텍스트에서 계산 되기 때문에 컴파일 시간 오류를 보고 합니다.the overflows that occur when evaluating the constant expressions in F and H cause compile-time errors to be reported because the expressions are evaluated in a checked context. 오버플로는 G에서 상수 식을 계산할 때에도 발생 하지만 평가는 @no__t 1 컨텍스트에서 발생 하므로 오버플로는 보고 되지 않습니다.An overflow also occurs when evaluating the constant expression in G, but since the evaluation takes place in an unchecked context, the overflow is not reported.

@No__t-0 및 unchecked 연산자는 "(" 및 ")" 토큰에 포함 된 작업에 대 한 오버플로 검사 컨텍스트에서만 영향을 줍니다.The checked and unchecked operators only affect the overflow checking context for those operations that are textually contained within the "(" and ")" tokens. 연산자는 포함 된 식을 평가한 결과로 호출 되는 함수 멤버에는 영향을 주지 않습니다.The operators have no effect on function members that are invoked as a result of evaluating the contained expression. 예제에서In the example

class Test
{
    static int Multiply(int x, int y) {
        return x * y;
    }

    static int F() {
        return checked(Multiply(1000000, 1000000));
    }
}

F에서 checked을 사용 해도-3 @no__t의 x * y에 영향을 주지 않으므로 기본 오버플로 검사 컨텍스트에서 x * y가 계산 됩니다.the use of checked in F does not affect the evaluation of x * y in Multiply, so x * y is evaluated in the default overflow checking context.

@No__t-0 연산자는 부호 있는 정수 형식의 상수를 16 진수 표기법으로 작성 하는 경우에 편리 합니다.The unchecked operator is convenient when writing constants of the signed integral types in hexadecimal notation. 예를 들어 다음과 같은 가치를 제공해야 합니다.For example:

class Test
{
    public const int AllBits = unchecked((int)0xFFFFFFFF);

    public const int HighBit = unchecked((int)0x80000000);
}

위의 두 16 진수 상수는 모두 uint 형식입니다.Both of the hexadecimal constants above are of type uint. 상수가 unchecked 연산자 없이 int 범위를 벗어나므로 int로 캐스팅 하면 컴파일 시간 오류가 발생 합니다.Because the constants are outside the int range, without the unchecked operator, the casts to int would produce compile-time errors.

@No__t-0 및 unchecked 연산자 및 문을 사용 하 여 프로그래머는 일부 숫자 계산의 특정 측면을 제어할 수 있습니다.The checked and unchecked operators and statements allow programmers to control certain aspects of some numeric calculations. 그러나 일부 숫자 연산자의 동작은 해당 피연산자의 데이터 형식에 따라 달라 집니다.However, the behavior of some numeric operators depends on their operands' data types. 예를 들어 두 개의 10 진수를 곱하여 명시적 unchecked 구문 내 에서도 오버플로에 대 한 예외가 발생 합니다.For example, multiplying two decimals always results in an exception on overflow even within an explicitly unchecked construct. 마찬가지로, 두 float을 곱하여 명시적 checked 구문 내 에서도 오버플로에 대 한 예외가 발생 하지 않습니다.Similarly, multiplying two floats never results in an exception on overflow even within an explicitly checked construct. 또한 다른 연산자는 기본값 또는 명시적 인지 여부를 확인 하는 모드의 영향을 받지 않습니다.In addition, other operators are never affected by the mode of checking, whether default or explicit.

기본값 식Default value expressions

기본 값 식은 형식의 기본값 (기본값)을 가져오는 데 사용 됩니다.A default value expression is used to obtain the default value (Default values) of a type. 일반적으로 형식 매개 변수가 값 형식 또는 참조 형식이 면 알려지지 않을 수 있기 때문에 일반적으로 형식 매개 변수에 대해 기본 값 식이 사용 됩니다.Typically a default value expression is used for type parameters, since it may not be known if the type parameter is a value type or a reference type. (형식 매개 변수를 참조 형식으로 알 수 없는 경우에는 null 리터럴에서 형식 매개 변수에 대 한 변환이 존재 하지 않습니다.)(No conversion exists from the null literal to a type parameter unless the type parameter is known to be a reference type.)

default_value_expression
    : 'default' '(' type ')'
    ;

Default_value_expression형식이 런타임에 참조 형식으로 계산 되는 경우 결과는 해당 형식으로 변환 된 null입니다.If the type in a default_value_expression evaluates at run-time to a reference type, the result is null converted to that type. Default_value_expression형식이 런타임에 값 형식으로 계산 되는 경우 결과는 value_type의 기본값 (기본 생성자)입니다.If the type in a default_value_expression evaluates at run-time to a value type, the result is the value_type's default value (Default constructors).

Default_value_expression 는 형식이 참조 형식 이거나 참조 형식 (형식 매개 변수 제약 조건)으로 알려진 형식 매개 변수인 경우 상수 식 (상수식)입니다.A default_value_expression is a constant expression (Constant expressions) if the type is a reference type or a type parameter that is known to be a reference type (Type parameter constraints). 또한 형식이 sbyte, byte, short, ushort, int, uint, long, ulong, char, 0, 1, 2, 3의 값 형식 중 하나인 경우 default_value_expression 는 상수 식입니다. 또는 열거형 형식입니다.In addition, a default_value_expression is a constant expression if the type is one of the following value types: sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool, or any enumeration type.

식의 nameNameof expressions

Nameof_expression 는 프로그램 엔터티의 이름을 상수 문자열로 가져오는 데 사용 됩니다.A nameof_expression is used to obtain the name of a program entity as a constant string.

nameof_expression
    : 'nameof' '(' named_entity ')'
    ;

named_entity
    : simple_name
    | named_entity_target '.' identifier type_argument_list?
    ;

named_entity_target
    : 'this'
    | 'base'
    | named_entity 
    | predefined_type 
    | qualified_alias_member
    ;

문법적으로 named_entity 피연산자는 항상 식입니다.Grammatically speaking, the named_entity operand is always an expression. @No__t-0은 예약 키워드가 아니므로 식의 nameof 항상 단순 이름 nameof을 호출 하는 구문상 모호 합니다.Because nameof is not a reserved keyword, a nameof expression is always syntactically ambiguous with an invocation of the simple name nameof. 호환성을 위해 이름 nameof의 이름 조회 (단순 이름)가 성공 하면 호출이 유효한 지 여부에 관계 없이 식이 invocation_expression 으로 처리 됩니다.For compatibility reasons, if a name lookup (Simple names) of the name nameof succeeds, the expression is treated as an invocation_expression -- regardless of whether the invocation is legal. 그렇지 않으면 nameof_expression입니다.Otherwise it is a nameof_expression.

Nameof_expression named_entity 의 의미는 식의 의미입니다. 즉, simple_name, base_access 또는 member_access중 하나입니다.The meaning of the named_entity of a nameof_expression is the meaning of it as an expression; that is, either as a simple_name, a base_access or a member_access. 그러나 단순 이름멤버 액세스 에 설명 된 조회로 인해 인스턴스 멤버가 정적 컨텍스트에서 발견 되어 오류가 발생 하는 경우 nameof_expression 는 이러한 오류를 생성 하지 않습니다.However, where the lookup described in Simple names and Member access results in an error because an instance member was found in a static context, a nameof_expression produces no such error.

Type_argument_list을 포함 하도록 메서드 그룹을 지정 하는 named_entity 에 대 한 컴파일 타임 오류입니다.It is a compile-time error for a named_entity designating a method group to have a type_argument_list. Named_entity_target 의 형식은 dynamic 인 경우 컴파일 타임 오류가 발생 합니다.It is a compile time error for a named_entity_target to have the type dynamic.

Nameof_expressionstring 형식의 상수 식이 며 런타임에 영향을 주지 않습니다.A nameof_expression is a constant expression of type string, and has no effect at runtime. 특히 named_entity 는 평가 되지 않으며, 한정 된 할당 분석의 목적으로 무시 됩니다 (간단한 식에 대 한 일반 규칙).Specifically, its named_entity is not evaluated, and is ignored for the purposes of definite assignment analysis (General rules for simple expressions). 값은 다음과 같은 방식으로 변환 되는 선택적 최종 type_argument_list이전의 named_entity 의 마지막 식별자입니다.Its value is the last identifier of the named_entity before the optional final type_argument_list, transformed in the following way:

  • 접두사 ""@(사용 되는 경우)가 제거 됩니다.The prefix "@", if used, is removed.
  • unicode_escape_sequence 는 해당 하는 유니코드 문자로 변환 됩니다.Each unicode_escape_sequence is transformed into its corresponding Unicode character.
  • 모든 formatting_characters 제거 됩니다.Any formatting_characters are removed.

식별자가 같은지 테스트할 때 식별자 에 적용 되는 변환과 동일 합니다.These are the same transformations applied in Identifiers when testing equality between identifiers.

TODO: 예제TODO: examples

무명 메서드 식Anonymous method expressions

Anonymous_method_expression 는 익명 함수를 정의 하는 두 가지 방법 중 하나입니다.An anonymous_method_expression is one of two ways of defining an anonymous function. 이러한 내용은 익명 함수 식에 자세히 설명 되어 있습니다.These are further described in Anonymous function expressions.

단항 연산자Unary operators

@No__t-0, +, -, !, ~, ++, --, cast 및 @no__t 연산자를 단항 연산자 라고 합니다.The ?, +, -, !, ~, ++, --, cast, and await operators are called the unary operators.

unary_expression
    : primary_expression
    | null_conditional_expression
    | '+' unary_expression
    | '-' unary_expression
    | '!' unary_expression
    | '~' unary_expression
    | pre_increment_expression
    | pre_decrement_expression
    | cast_expression
    | await_expression
    | unary_expression_unsafe
    ;

Unary_expression 의 피연산자가-1 @no__t 컴파일 시간 형식인 경우 동적으로 바인딩됩니다 (동적 바인딩).If the operand of a unary_expression has the compile-time type dynamic, it is dynamically bound (Dynamic binding). 이 경우 @no__t unary_expression 의 컴파일 타임 형식은-1 이며 아래에 설명 된 해결 방법은 런타임에 런타임 형식을 사용 하 여 런타임에 수행 됩니다.In this case the compile-time type of the unary_expression is dynamic, and the resolution described below will take place at run-time using the run-time type of the operand.

Null 조건 연산자Null-conditional operator

Null 조건 연산자는 해당 피연산자가 null이 아닌 경우에만 해당 피연산자에 작업 목록을 적용 합니다.The null-conditional operator applies a list of operations to its operand only if that operand is non-null. 그렇지 않으면 연산자를 적용 한 결과가-0 @no__t 됩니다.Otherwise the result of applying the operator is null.

null_conditional_expression
    : primary_expression null_conditional_operations
    ;

null_conditional_operations
    : null_conditional_operations? '?' '.' identifier type_argument_list?
    | null_conditional_operations? '?' '[' argument_list ']'
    | null_conditional_operations '.' identifier type_argument_list?
    | null_conditional_operations '[' argument_list ']'
    | null_conditional_operations '(' argument_list? ')'
    ;

작업 목록에는 호출 뿐만 아니라 멤버 액세스 및 요소 액세스 작업 (자체 null 조건부 일 수 있음)이 포함 될 수 있습니다.The list of operations can include member access and element access operations (which may themselves be null-conditional), as well as invocation.

예를 들어 a.b?[0]?.c() 식은 primary_expression a.bnull_conditional_operations ?[0] (null 조건부 요소 액세스) ?.c (null-조건부 멤버) 인 null_conditional_expression 입니다. 액세스) 및 () (호출)을 사용 합니다.For example, the expression a.b?[0]?.c() is a null_conditional_expression with a primary_expression a.b and null_conditional_operations ?[0] (null-conditional element access), ?.c (null-conditional member access) and () (invocation).

Primary_expression Pnull_conditional_expression E의 경우 E의 각 null_conditional_operations 에서 선행 ?를 제거 하는 식으로 E0를 사용 합니다. 하나 있습니다.For a null_conditional_expression E with a primary_expression P, let E0 be the expression obtained by textually removing the leading ? from each of the null_conditional_operations of E that have one. 개념적으로 E0은 @no__t에 의해 표시 된 null 검사가 없는 경우 계산 되는 식입니다.-1은 null를 찾습니다.Conceptually, E0 is the expression that will be evaluated if none of the null checks represented by the ?s do find a null.

또한 E1E의 첫 번째 null_conditional_operations 에서 선행 ?을 제거 하 여 가져온 식입니다.Also, let E1 be the expression obtained by textually removing the leading ? from just the first of the null_conditional_operations in E. 이 경우 기본 식 (1 ?만 있는 경우) 또는 다른 null_conditional_expression될 수 있습니다.This may lead to a primary-expression (if there was just one ?) or to another null_conditional_expression.

예를 들어 E이-@no__t 1 @no__t 식 인 경우-2는-3 @no__t, E1는 식 a.b[0]?.c()입니다.For example, if E is the expression a.b?[0]?.c(), then E0 is the expression a.b[0].c() and E1 is the expression a.b[0]?.c().

@No__t-0이 nothing으로 분류 되 면 E이 nothing으로 분류 됩니다.If E0 is classified as nothing, then E is classified as nothing. 그렇지 않으면 E는 값으로 분류 됩니다.Otherwise E is classified as a value.

E0E1E의 의미를 확인 하는 데 사용 됩니다.E0 and E1 are used to determine the meaning of E:

  • @No__t-0이 statement_expression 경우-2 @no__t의 의미는 문과 동일 합니다.If E occurs as a statement_expression the meaning of E is the same as the statement

    if ((object)P != null) E1;
    

    P는 한 번만 계산 된다는 점이 다릅니다.except that P is evaluated only once.

  • 그렇지 않고 E0은 컴파일 시간 오류가 발생 하지 않습니다.Otherwise, if E0 is classified as nothing a compile-time error occurs.

  • 그렇지 않으면-0 @no__t @no__t의 유형입니다.Otherwise, let T0 be the type of E0.

    • @No__t-0은 참조 형식 또는 nullable이 아닌 값 형식으로 알려지지 않은 형식 매개 변수 이면 컴파일 시간 오류가 발생 합니다.If T0 is a type parameter that is not known to be a reference type or a non-nullable value type, a compile-time error occurs.

    • @No__t-0이 null을 허용 하지 않는 값 형식인 경우-1 @no__t의 형식은 T0?이 고 E의 의미는와 동일 합니다.If T0 is a non-nullable value type, then the type of E is T0?, and the meaning of E is the same as

      ((object)P == null) ? (T0?)null : E1
      

      단, P은 한 번만 평가 됩니다.except that P is evaluated only once.

    • 그렇지 않으면 E의 형식은 T0이 고 E의 의미는와 동일 합니다.Otherwise the type of E is T0, and the meaning of E is the same as

      ((object)P == null) ? null : E1
      

      단, P은 한 번만 평가 됩니다.except that P is evaluated only once.

@No__t-0이 자체가 null_conditional_expression경우 이러한 규칙은 다시 적용 되 고, 추가 ?이 없을 때까지 null에 대 한 테스트를 중첩 하며, 식이 기본 식 E0까지 모두 축소 된 것입니다.If E1 is itself a null_conditional_expression, then these rules are applied again, nesting the tests for null until there are no further ?'s, and the expression has been reduced all the way down to the primary-expression E0.

예를 들어 a.b?[0]?.c() 식이 문과 같이 문 식으로 발생 합니다.For example, if the expression a.b?[0]?.c() occurs as a statement-expression, as in the statement:

a.b?[0]?.c();

의미는 다음과 같습니다.its meaning is equivalent to:

if (a.b != null) a.b[0]?.c();

다시 다음에 해당 합니다.which again is equivalent to:

if (a.b != null) if (a.b[0] != null) a.b[0].c();

단, a.ba.b[0]은 한 번만 평가 됩니다.Except that a.b and a.b[0] are evaluated only once.

다음과 같이 값이 사용 되는 컨텍스트에서 발생 하는 경우If it occurs in a context where its value is used, as in:

var x = a.b?[0]?.c();

최종 호출의 형식이 null을 허용 하지 않는 값 형식이 아닌 것으로 가정 하 여 해당 의미는 다음과 같습니다.and assuming that the type of the final invocation is not a non-nullable value type, its meaning is equivalent to:

var x = (a.b == null) ? null : (a.b[0] == null) ? null : a.b[0].c();

단, a.ba.b[0]은 한 번만 평가 됩니다.except that a.b and a.b[0] are evaluated only once.

Null 조건부 식 (프로젝션 이니셜라이저)Null-conditional expressions as projection initializers

Null 조건부 식은 (선택적으로 null 조건) 멤버 액세스로 끝나는 경우 anonymous_object_creation_expression (익명 개체 생성 식)에서 member_declarator 로 사용할 수 있습니다.A null-conditional expression is only allowed as a member_declarator in an anonymous_object_creation_expression (Anonymous object creation expressions) if it ends with an (optionally null-conditional) member access. 문법적으로이 요구 사항은 다음과 같이 표현 될 수 있습니다.Grammatically, this requirement can be expressed as:

null_conditional_member_access
    : primary_expression null_conditional_operations? '?' '.' identifier type_argument_list?
    | primary_expression null_conditional_operations '.' identifier type_argument_list?
    ;

위의 null_conditional_expression 에 대 한 문법의 특별 한 사례입니다.This is a special case of the grammar for null_conditional_expression above. 익명 개체 생성 식member_declarator 에 대 한 프로덕션에는 null_conditional_member_access만 포함 됩니다.The production for member_declarator in Anonymous object creation expressions then includes only null_conditional_member_access.

Null 조건식을 문 식으로Null-conditional expressions as statement expressions

Null 조건 식은 호출로 끝나는 경우 statement_expression (식 문)로만 사용할 수 있습니다.A null-conditional expression is only allowed as a statement_expression (Expression statements) if it ends with an invocation. 문법적으로이 요구 사항은 다음과 같이 표현 될 수 있습니다.Grammatically, this requirement can be expressed as:

null_conditional_invocation_expression
    : primary_expression null_conditional_operations '(' argument_list? ')'
    ;

위의 null_conditional_expression 에 대 한 문법의 특별 한 사례입니다.This is a special case of the grammar for null_conditional_expression above. Expression 문에 대 한 production statement_expressionnull_conditional_invocation_expression만 포함 합니다.The production for statement_expression in Expression statements then includes only null_conditional_invocation_expression.

단항 더하기 연산자Unary plus operator

@No__t-0 형식의 작업에 대해 단항 연산자 오버 로드 확인 (단항 연산자 오버 로드 확인)이 적용 되어 특정 연산자 구현을 선택 합니다.For an operation of the form +x, unary operator overload resolution (Unary operator overload resolution) is applied to select a specific operator implementation. 피연산자는 선택한 연산자의 매개 변수 형식으로 변환 되 고 결과의 형식은 연산자의 반환 형식입니다.The operand is converted to the parameter type of the selected operator, and the type of the result is the return type of the operator. 미리 정의 된 단항 더하기 연산자는 다음과 같습니다.The predefined unary plus operators are:

int operator +(int x);
uint operator +(uint x);
long operator +(long x);
ulong operator +(ulong x);
float operator +(float x);
double operator +(double x);
decimal operator +(decimal x);

이러한 각 연산자에 대해 결과는 단순히 피연산자의 값입니다.For each of these operators, the result is simply the value of the operand.

단항 빼기 연산자Unary minus operator

@No__t-0 형식의 작업에 대해 단항 연산자 오버 로드 확인 (단항 연산자 오버 로드 확인)이 적용 되어 특정 연산자 구현을 선택 합니다.For an operation of the form -x, unary operator overload resolution (Unary operator overload resolution) is applied to select a specific operator implementation. 피연산자는 선택한 연산자의 매개 변수 형식으로 변환 되 고 결과의 형식은 연산자의 반환 형식입니다.The operand is converted to the parameter type of the selected operator, and the type of the result is the return type of the operator. 미리 정의 된 부정 연산자는 다음과 같습니다.The predefined negation operators are:

  • 정수 부정:Integer negation:

    int operator -(int x);
    long operator -(long x);
    

    0에서 0 @no__t 빼서 결과가 계산 됩니다.The result is computed by subtracting x from zero. @No__t-0의 값이 피연산자 유형 (-2 ^ 31 (long)의 경우-2 ^ @no__t 31)의 표현 가능한 가장 작은 값인 경우에는 피연산자 형식 내에서 x의 수학 부정을 표현할 수 없습니다.If the value of x is the smallest representable value of the operand type (-2^31 for int or -2^63 for long), then the mathematical negation of x is not representable within the operand type. @No__t-0 컨텍스트 내에서 발생 하는 경우 System.OverflowException이 throw 됩니다. unchecked 컨텍스트 내에서 발생 하는 경우 결과는 피연산자의 값이 고 오버플로는 보고 되지 않습니다.If this occurs within a checked context, a System.OverflowException is thrown; if it occurs within an unchecked context, the result is the value of the operand and the overflow is not reported.

    부정 연산자의 피연산자의 형식이 uint 인 경우 long 형식으로 변환 되 고 결과의 형식은-2 @no__t 됩니다.If the operand of the negation operator is of type uint, it is converted to type long, and the type of the result is long. 예외는 int 값-2147483648 (-2 ^ 31)을 10 진수 정수 리터럴 (정수 리터럴)로 쓸 수 있도록 허용 하는 규칙입니다.An exception is the rule that permits the int value -2147483648 (-2^31) to be written as a decimal integer literal (Integer literals).

    부정 연산자의 피연산자의 형식이 ulong 이면 컴파일 시간 오류가 발생 합니다.If the operand of the negation operator is of type ulong, a compile-time error occurs. 예외는 long 값-9223372036854775808 (-2 ^ 63)을 10 진수 정수 리터럴 (정수 리터럴)으로 쓸 수 있도록 허용 하는 규칙입니다.An exception is the rule that permits the long value -9223372036854775808 (-2^63) to be written as a decimal integer literal (Integer literals).

  • 부동 소수점 부정:Floating-point negation:

    float operator -(float x);
    double operator -(double x);
    

    결과는 부호가 반전 된 x의 값입니다.The result is the value of x with its sign inverted. @No__t-0이 NaN 이면 결과도 NaN입니다.If x is NaN, the result is also NaN.

  • 소수점 부정:Decimal negation:

    decimal operator -(decimal x);
    

    0에서 0 @no__t 빼서 결과가 계산 됩니다.The result is computed by subtracting x from zero. 소수점 부정은 System.Decimal 형식의 단항 빼기 연산자를 사용 하는 것과 같습니다.Decimal negation is equivalent to using the unary minus operator of type System.Decimal.

논리 부정 연산자Logical negation operator

@No__t-0 형식의 작업에 대해 단항 연산자 오버 로드 확인 (단항 연산자 오버 로드 확인)이 적용 되어 특정 연산자 구현을 선택 합니다.For an operation of the form !x, unary operator overload resolution (Unary operator overload resolution) is applied to select a specific operator implementation. 피연산자는 선택한 연산자의 매개 변수 형식으로 변환 되 고 결과의 형식은 연산자의 반환 형식입니다.The operand is converted to the parameter type of the selected operator, and the type of the result is the return type of the operator. 미리 정의 된 논리 부정 연산자는 하나만 존재 합니다.Only one predefined logical negation operator exists:

bool operator !(bool x);

이 연산자는 피연산자의 논리 부정을 계산 합니다. 피연산자가 0 @no__t 이면 결과는-1이 @no__t 됩니다.This operator computes the logical negation of the operand: If the operand is true, the result is false. 피연산자가 0 @no__t 이면 결과는-1이 @no__t 됩니다.If the operand is false, the result is true.

비트 보수 연산자Bitwise complement operator

@No__t-0 형식의 작업에 대해 단항 연산자 오버 로드 확인 (단항 연산자 오버 로드 확인)이 적용 되어 특정 연산자 구현을 선택 합니다.For an operation of the form ~x, unary operator overload resolution (Unary operator overload resolution) is applied to select a specific operator implementation. 피연산자는 선택한 연산자의 매개 변수 형식으로 변환 되 고 결과의 형식은 연산자의 반환 형식입니다.The operand is converted to the parameter type of the selected operator, and the type of the result is the return type of the operator. 미리 정의 된 비트 보수 연산자는 다음과 같습니다.The predefined bitwise complement operators are:

int operator ~(int x);
uint operator ~(uint x);
long operator ~(long x);
ulong operator ~(ulong x);

이러한 각 연산자에 대해 연산의 결과는 x의 비트 보수입니다.For each of these operators, the result of the operation is the bitwise complement of x.

모든 열거형 형식 E은 암시적으로 다음 비트 보수 연산자를 제공 합니다.Every enumeration type E implicitly provides the following bitwise complement operator:

E operator ~(E x);

@No__t-@no__t 0을 평가한 결과-1은 기본 형식이 U 인 열거형 형식 E 인 식입니다. 즉, E로 변환 하는 것은 항상 unchecked 컨텍스트에서와 동일 하 게 수행 됩니다. Checked 및 unchecked 연산자).The result of evaluating ~x, where x is an expression of an enumeration type E with an underlying type U, is exactly the same as evaluating (E)(~(U)x), except that the conversion to E is always performed as if in an unchecked context (The checked and unchecked operators).

전위 증가 및 감소 연산자Prefix increment and decrement operators

pre_increment_expression
    : '++' unary_expression
    ;

pre_decrement_expression
    : '--' unary_expression
    ;

전위 증가 또는 감소 연산의 피연산자는 변수, 속성 액세스 또는 인덱서 액세스로 분류 된 식 이어야 합니다.The operand of a prefix increment or decrement operation must be an expression classified as a variable, a property access, or an indexer access. 작업의 결과는 피연산자와 동일한 형식의 값입니다.The result of the operation is a value of the same type as the operand.

전위 증가 또는 감소 연산의 피연산자가 속성 또는 인덱서 액세스 인 경우 속성 또는 인덱서에 getset 접근자가 둘 다 있어야 합니다.If the operand of a prefix increment or decrement operation is a property or indexer access, the property or indexer must have both a get and a set accessor. 이러한 경우가 아니면 바인딩 시간 오류가 발생 합니다.If this is not the case, a binding-time error occurs.

특정 연산자 구현을 선택 하기 위해 단항 연산자 오버 로드 확인 (단항 연산자 오버 로드 확인)이 적용 됩니다.Unary operator overload resolution (Unary operator overload resolution) is applied to select a specific operator implementation. 미리 정의 된 ++-- 연산자는 sbyte, byte, short, ushort, int, uint, long, ulong, 0, 1, 2, 3 및 모든 열거형 형식에 대해 존재 합니다.Predefined ++ and -- operators exist for the following types: sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, and any enum type. 미리 정의 된 ++ 연산자는 피연산자에 1을 더하여 생성 된 값을 반환 하 고 미리 정의 된 -- 연산자는 피연산자에서 1을 빼서 생성 된 값을 반환 합니다.The predefined ++ operators return the value produced by adding 1 to the operand, and the predefined -- operators return the value produced by subtracting 1 from the operand. @No__t-0 컨텍스트에서이 더하기 또는 빼기의 결과가 결과 형식의 범위를 벗어나면 결과 형식이 정수 형식 또는 열거형 형식이 면 System.OverflowException이 throw 됩니다.In a checked context, if the result of this addition or subtraction is outside the range of the result type and the result type is an integral type or enum type, a System.OverflowException is thrown.

@No__t-0 또는 --x 형식의 전위 증가 또는 감소 연산의 런타임 처리는 다음 단계로 구성 됩니다.The run-time processing of a prefix increment or decrement operation of the form ++x or --x consists of the following steps:

  • @No__t-0은 변수로 분류 됩니다.If x is classified as a variable:
    • x을 계산 하 여 변수를 생성 합니다.x is evaluated to produce the variable.
    • 선택한 연산자는 @no__t 값을 인수로 사용 하 여 호출 됩니다.The selected operator is invoked with the value of x as its argument.
    • 연산자에서 반환 되는 값은 x의 계산에 지정 된 위치에 저장 됩니다.The value returned by the operator is stored in the location given by the evaluation of x.
    • 연산자에서 반환 되는 값은 작업의 결과가 됩니다.The value returned by the operator becomes the result of the operation.
  • @No__t-0은 속성 또는 인덱서 액세스로 분류 됩니다.If x is classified as a property or indexer access:
    • 인스턴스 식 (xstatic이 아닌 경우) 및 x과 연결 된 인수 목록 (x가 인덱서 액세스 인 경우)이 평가 되 고 이후 getset 접근자 호출에서 결과가 사용 됩니다.The instance expression (if x is not static) and the argument list (if x is an indexer access) associated with x are evaluated, and the results are used in the subsequent get and set accessor invocations.
    • @No__t-1의 get 접근자가 호출 됩니다.The get accessor of x is invoked.
    • @No__t-0 접근자에 의해 반환 된 값을 인수로 사용 하 여 선택한 연산자가 호출 됩니다.The selected operator is invoked with the value returned by the get accessor as its argument.
    • @No__t-1의 set 접근자는 연산자가 value 인수로 반환 하는 값으로 호출 됩니다.The set accessor of x is invoked with the value returned by the operator as its value argument.
    • 연산자에서 반환 되는 값은 작업의 결과가 됩니다.The value returned by the operator becomes the result of the operation.

@No__t-0 및 -- 연산자는 후 위 표기법 (후 위 증가 및 감소 연산자)도 지원 합니다.The ++ and -- operators also support postfix notation (Postfix increment and decrement operators). 일반적으로 x++ 또는 x--의 결과는 작업 이전에 x의 값이 고, ++x 또는 --x의 결과는 작업 후에 x의 값입니다.Typically, the result of x++ or x-- is the value of x before the operation, whereas the result of ++x or --x is the value of x after the operation. 두 경우 모두 x은 작업 후에 동일한 값을 갖습니다.In either case, x itself has the same value after the operation.

@No__t-0 또는 operator-- 구현은 후 위 또는 접두사 표기법을 사용 하 여 호출할 수 있습니다.An operator++ or operator-- implementation can be invoked using either postfix or prefix notation. 두 표기법에 대해 별도의 연산자 구현을 사용할 수 없습니다.It is not possible to have separate operator implementations for the two notations.

캐스트 식Cast expressions

Cast_expression 는 식을 지정 된 형식으로 명시적으로 변환 하는 데 사용 됩니다.A cast_expression is used to explicitly convert an expression to a given type.

cast_expression
    : '(' type ')' unary_expression
    ;

@No__t-1 형식의 cast_expression (T형식이 고, Eunary_expression인 경우, E 값의 명시적 변환 (명시적변환)을 T 형식으로 수행 합니다.A cast_expression of the form (T)E, where T is a type and E is a unary_expression, performs an explicit conversion (Explicit conversions) of the value of E to type T. @No__t-0에서 T로의 명시적 변환이 없는 경우 바인딩 시간 오류가 발생 합니다.If no explicit conversion exists from E to T, a binding-time error occurs. 그렇지 않으면 결과는 명시적 변환에 의해 생성 된 값입니다.Otherwise, the result is the value produced by the explicit conversion. @No__t-0이 변수를 나타내는 경우에도 결과는 항상 값으로 분류 됩니다.The result is always classified as a value, even if E denotes a variable.

Cast_expression 에 대 한 문법은 특정 구문 모호성을 초래 합니다.The grammar for a cast_expression leads to certain syntactic ambiguities. 예를 들어 (x)-y 식은 cast_expression (형식 x으로 @no__t의 캐스트) 또는 parenthesized_expression 와 결합 된 additive_expression 로 해석 될 수 있습니다 .이 값은-6 @no__t 값을 계산 합니다.For example, the expression (x)-y could either be interpreted as a cast_expression (a cast of -y to type x) or as an additive_expression combined with a parenthesized_expression (which computes the value x - y).

Cast_expression 모호성을 해결 하기 위해 다음 규칙이 있습니다. 다음 중 하나 이상이 true 인 경우에만 괄호로 묶인 하나 이상의 토큰s (공백) 시퀀스가 cast_expression 의 시작 부분으로 간주 됩니다.To resolve cast_expression ambiguities, the following rule exists: A sequence of one or more tokens (White space) enclosed in parentheses is considered the start of a cast_expression only if at least one of the following are true:

  • 토큰 시퀀스는 형식에 대 한 올바른 문법 이지만 식이아닙니다.The sequence of tokens is correct grammar for a type, but not for an expression.
  • 토큰 시퀀스는 형식에 대 한 올바른 문법 이며 닫는 괄호 바로 다음에 오는 토큰은 토큰 "~", 토큰 "!", 토큰 "(", 식별자 (유니코드 문자 이스케이프 시퀀스)입니다. ), 리터럴 (리터럴) 또는0 및 1을 제외한 모든 키워드 (키워드)입니다.The sequence of tokens is correct grammar for a type, and the token immediately following the closing parentheses is the token "~", the token "!", the token "(", an identifier (Unicode character escape sequences), a literal (Literals), or any keyword (Keywords) except as and is.

위의 "올바른 문법" 이라는 용어는 토큰 시퀀스가 특정 문법 프로덕션을 준수 해야 한다는 것을 의미 합니다.The term "correct grammar" above means only that the sequence of tokens must conform to the particular grammatical production. 구체적으로는 모든 구성 식별자의 실제 의미를 고려 하지 않습니다.It specifically does not consider the actual meaning of any constituent identifiers. 예를 들어 x이 고 y이 식별자 이면 x.y이 실제로 형식을 표시 하지 않더라도 x.y는 형식에 대 한 올바른 문법입니다.For example, if x and y are identifiers, then x.y is correct grammar for a type, even if x.y doesn't actually denote a type.

명확성 규칙에서 xy은 식별자이 고, (x)y, (x)(y), (x)(-y)cast_expressions 인 경우 x은 형식을 식별 하더라도 (x)-y은 그렇지 않습니다.From the disambiguation rule it follows that, if x and y are identifiers, (x)y, (x)(y), and (x)(-y) are cast_expressions, but (x)-y is not, even if x identifies a type. 그러나 x이 미리 정의 된 형식 (예: int)을 식별 하는 키워드인 경우 이러한 키워드는 자체적으로 식이 될 수 없으므로 4 가지 형태가 모두 cast_expressions입니다.However, if x is a keyword that identifies a predefined type (such as int), then all four forms are cast_expressions (because such a keyword could not possibly be an expression by itself).

Wait 식Await expressions

Wait 연산자는 피연산자로 표시 되는 비동기 작업이 완료 될 때까지 바깥쪽 비동기 함수의 계산을 일시 중단 하는 데 사용 됩니다.The await operator is used to suspend evaluation of the enclosing async function until the asynchronous operation represented by the operand has completed.

await_expression
    : 'await' unary_expression
    ;

Await_expression 는 비동기 함수 (반복기)의 본문 에서만 사용할 수 있습니다.An await_expression is only allowed in the body of an async function (Iterators). 가장 가까운 바깥쪽 async 함수 내에서 await_expression 는 다음 위치에서 발생 하지 않을 수 있습니다.Within the nearest enclosing async function, an await_expression may not occur in these places:

  • 중첩 된 (비 async) 익명 함수 내부Inside a nested (non-async) anonymous function
  • Lock_statement 블록 내부Inside the block of a lock_statement
  • 안전 하지 않은 컨텍스트에서In an unsafe context

Query_expression내에서 대부분의 위치에 await_expression 를 사용할 수 없습니다 .이는 구문적으로 비 비동기 람다 식을 사용 하기 위해 변환 되기 때문입니다.Note that an await_expression cannot occur in most places within a query_expression, because those are syntactically transformed to use non-async lambda expressions.

비동기 함수 내에서 await을 식별자로 사용할 수 없습니다.Inside of an async function, await cannot be used as an identifier. 따라서 wait 식과 식별자를 포함 하는 다양 한 식 사이에는 구문상 모호성이 없습니다.There is therefore no syntactic ambiguity between await-expressions and various expressions involving identifiers. 비동기 함수 외부에서 await은 일반 식별자 역할을 합니다.Outside of async functions, await acts as a normal identifier.

Await_expression 의 피연산자를 작업이라고 합니다.The operand of an await_expression is called the task. Await_expression 을 평가할 때 완료 될 수도 있고 완료 되지 않을 수도 있는 비동기 작업을 나타냅니다.It represents an asynchronous operation that may or may not be complete at the time the await_expression is evaluated. Wait 연산자의 목적은 대기 작업이 완료 될 때까지 바깥쪽 async 함수의 실행을 일시 중단 한 다음 해당 결과를 가져오는 것입니다.The purpose of the await operator is to suspend execution of the enclosing async function until the awaited task is complete, and then obtain its outcome.

대기 가능 식Awaitable expressions

Wait 식의 작업은 대기 가능이 필요 합니다.The task of an await expression is required to be awaitable. 다음 중 하나에 해당 하는 경우 t은 대기 가능입니다.An expression t is awaitable if one of the following holds:

  • t은 컴파일 시간 형식이 dynamic입니다.t is of compile time type dynamic
  • t에는 매개 변수가 없고 형식 매개 변수 없이 GetAwaiter 이라는 액세스 가능한 인스턴스 또는 확장 메서드가 있으며, 다음 모두에 해당 하는 반환 형식 A가 포함 됩니다.t has an accessible instance or extension method called GetAwaiter with no parameters and no type parameters, and a return type A for which all of the following hold:
    • A은 @no__t @no__t 인터페이스를 구현 합니다.A implements the interface System.Runtime.CompilerServices.INotifyCompletion (hereafter known as INotifyCompletion for brevity)
    • A에는 bool 형식의 IsCompleted 인 액세스 가능 하 고 읽을 수 있는 인스턴스 속성이 있습니다.A has an accessible, readable instance property IsCompleted of type bool
    • @no__t에는 매개 변수가 없고 형식 매개 변수가 없는-1 @no__t 액세스 가능한 인스턴스 메서드가 있습니다.A has an accessible instance method GetResult with no parameters and no type parameters

@No__t-0 메서드의 목적은 태스크에 대 한 awaiter 를 가져오는 것입니다.The purpose of the GetAwaiter method is to obtain an awaiter for the task. @No__t-0 유형을 wait 식에 대 한 awaiter 유형 이라고 합니다.The type A is called the awaiter type for the await expression.

@No__t-0 속성은 작업이 이미 완료 되었는지 여부를 확인 하기 위한 것입니다.The purpose of the IsCompleted property is to determine if the task is already complete. 그렇다면 평가를 일시 중단할 필요가 없습니다.If so, there is no need to suspend evaluation.

@No__t-0 메서드의 목적은 "연속"을 작업에 등록 하는 것입니다. 즉, 작업이 완료 되 면 호출 되는 대리자 (형식 System.Action)입니다.The purpose of the INotifyCompletion.OnCompleted method is to sign up a "continuation" to the task; i.e. a delegate (of type System.Action) that will be invoked once the task is complete.

@No__t-0 메서드는 작업이 완료 되 면 작업의 결과를 가져오는 데 목적이 있습니다.The purpose of the GetResult method is to obtain the outcome of the task once it is complete. 이 결과는 결과 값을 사용 하 여 성공적으로 완료 될 수도 있고 GetResult 메서드에서 throw 되는 예외 일 수도 있습니다.This outcome may be successful completion, possibly with a result value, or it may be an exception which is thrown by the GetResult method.

Wait 식의 분류Classification of await expressions

await t은 식 (t).GetAwaiter().GetResult()과 동일한 방식으로 분류 됩니다.The expression await t is classified the same way as the expression (t).GetAwaiter().GetResult(). 따라서 GetResult의 반환 형식이-1 @no__t 경우 await_expression 는 nothing으로 분류 됩니다.Thus, if the return type of GetResult is void, the await_expression is classified as nothing. Void가 아닌 반환 형식이 T 인 경우 await_expression 은 형식 T 형식 값으로 분류 됩니다.If it has a non-void return type T, the await_expression is classified as a value of type T.

Wait 식의 런타임 계산Runtime evaluation of await expressions

런타임에 식 await t은 다음과 같이 계산 됩니다.At runtime, the expression await t is evaluated as follows:

  • Awaiter a은-1 @no__t 식을 계산 하 여 가져옵니다.An awaiter a is obtained by evaluating the expression (t).GetAwaiter().
  • @No__t-0 @no__t은 식 (a).IsCompleted를 계산 하 여 구합니다.A bool b is obtained by evaluating the expression (a).IsCompleted.
  • @No__t-0이 false 이면 a가-@no__t 3 @no__t 인터페이스를 구현 하는지 여부에 따라 계산 됩니다.If b is false then evaluation depends on whether a implements the interface System.Runtime.CompilerServices.ICriticalNotifyCompletion (hereafter known as ICriticalNotifyCompletion for brevity). 이 검사는 바인딩 시에 수행 됩니다. 즉, a에 컴파일 시간 형식이-1 인 경우에는 런타임 시이 고, 그렇지 않으면 컴파일 시간에 @no__t.This check is done at binding time; i.e. at runtime if a has the compile time type dynamic, and at compile time otherwise. @No__t-0은 다시 시작 대리자 (반복기)를 나타냅니다.Let r denote the resumption delegate (Iterators):
    • @No__t-0 ICriticalNotifyCompletion을 구현 하지 않으면-2 @no__t 식이 계산 됩니다.If a does not implement ICriticalNotifyCompletion, then the expression (a as (INotifyCompletion)).OnCompleted(r) is evaluated.
    • @No__t-0 @no__t를 구현 하면-2 @no__t 식이 계산 됩니다.If a does implement ICriticalNotifyCompletion, then the expression (a as (ICriticalNotifyCompletion)).UnsafeOnCompleted(r) is evaluated.
    • 그런 다음 평가가 일시 중단 되 고 제어가 비동기 함수의 현재 호출자에 게 반환 됩니다.Evaluation is then suspended, and control is returned to the current caller of the async function.
  • 바로 뒤 (btrue) 이거나 나중에 다시 시작 대리자를 호출 하는 경우 (bfalse 인 경우) @no__t 식이 계산 됩니다.Either immediately after (if b was true), or upon later invocation of the resumption delegate (if b was false), the expression (a).GetResult() is evaluated. 값을 반환 하는 경우 해당 값은 await_expression의 결과입니다.If it returns a value, that value is the result of the await_expression. 그렇지 않으면 아무 것도 반환 되지 않습니다.Otherwise the result is nothing.

Awaiter의 인터페이스 메서드 구현에 INotifyCompletion.OnCompletedICriticalNotifyCompletion.UnsafeOnCompleted을 지정 하면 대리자 r가 한 번만 호출 됩니다.An awaiter's implementation of the interface methods INotifyCompletion.OnCompleted and ICriticalNotifyCompletion.UnsafeOnCompleted should cause the delegate r to be invoked at most once. 그렇지 않으면 바깥쪽 비동기 함수의 동작이 정의 되지 않습니다.Otherwise, the behavior of the enclosing async function is undefined.

산술 연산자Arithmetic operators

@No__t-0, /, %, + 및 @no__t 연산자를 산술 연산자 라고 합니다.The *, /, %, +, and - operators are called the arithmetic operators.

multiplicative_expression
    : unary_expression
    | multiplicative_expression '*' unary_expression
    | multiplicative_expression '/' unary_expression
    | multiplicative_expression '%' unary_expression
    ;

additive_expression
    : multiplicative_expression
    | additive_expression '+' multiplicative_expression
    | additive_expression '-' multiplicative_expression
    ;

산술 연산자의 피연산자에 컴파일 타임 형식 dynamic이 있으면 식이 동적으로 바인딩됩니다 (동적 바인딩).If an operand of an arithmetic operator has the compile-time type dynamic, then the expression is dynamically bound (Dynamic binding). 이 경우 식의 컴파일 시간 형식은 dynamic 이며 아래에 설명 된 해결 방법은 컴파일 시간 @no__t 형식이-1 인 피연산자의 런타임 형식을 사용 하 여 런타임에 수행 됩니다.In this case the compile-time type of the expression is dynamic, and the resolution described below will take place at run-time using the run-time type of those operands that have the compile-time type dynamic.

곱하기 연산자Multiplication operator

@No__t-0 형식의 작업에 대해 이항 연산자 오버 로드 확인 (이진 연산자 오버 로드 확인)이 적용 되어 특정 연산자 구현을 선택 합니다.For an operation of the form x * y, binary operator overload resolution (Binary operator overload resolution) is applied to select a specific operator implementation. 피연산자는 선택한 연산자의 매개 변수 형식으로 변환 되 고 결과의 형식은 연산자의 반환 형식입니다.The operands are converted to the parameter types of the selected operator, and the type of the result is the return type of the operator.

미리 정의 된 곱하기 연산자는 아래에 나열 되어 있습니다.The predefined multiplication operators are listed below. 연산자는 모두 xy의 곱을 계산 합니다.The operators all compute the product of x and y.

  • 정수 곱하기:Integer multiplication:

    int operator *(int x, int y);
    uint operator *(uint x, uint y);
    long operator *(long x, long y);
    ulong operator *(ulong x, ulong y);
    

    @No__t-0 컨텍스트에서 제품이 결과 형식의 범위를 벗어나면 System.OverflowException이 throw 됩니다.In a checked context, if the product is outside the range of the result type, a System.OverflowException is thrown. @No__t-0 컨텍스트에서 오버플로는 보고 되지 않으며 결과 형식 범위 밖의 중요 한 상위 비트가 모두 삭제 됩니다.In an unchecked context, overflows are not reported and any significant high-order bits outside the range of the result type are discarded.

  • 부동 소수점 곱셈:Floating-point multiplication:

    float operator *(float x, float y);
    double operator *(double x, double y);
    

    제품은 IEEE 754 산술의 규칙에 따라 계산 됩니다.The product is computed according to the rules of IEEE 754 arithmetic. 다음 표에서는 0이 아닌 유한 값, 0, 무한대 및 NaN의 모든 가능한 조합에 대 한 결과를 보여 줍니다.The following table lists the results of all possible combinations of nonzero finite values, zeros, infinities, and NaN's. 표에서 xy은 양의 유한 값입니다.In the table, x and y are positive finite values. zx * y의 결과입니다.z is the result of x * y. 결과가 너무 커서 대상 형식에 맞지 않는 경우 z은 무한대입니다.If the result is too large for the destination type, z is infinity. 대상 유형에 대 한 결과가 너무 작은 경우 z이 0입니다.If the result is too small for the destination type, z is zero.

    + y+y -y-y +0+0 -0-0 +inf+inf -inf-inf NaNNaN
    +x+x +z+z -z-z +0+0 -0-0 +inf+inf -inf-inf NaNNaN
    -x-x -z-z +z+z -0-0 +0+0 -inf-inf +inf+inf NaNNaN
    +0+0 +0+0 -0-0 +0+0 -0-0 NaNNaN NaNNaN NaNNaN
    -0-0 -0-0 +0+0 -0-0 +0+0 NaNNaN NaNNaN NaNNaN
    +inf+inf +inf+inf -inf-inf NaNNaN NaNNaN +inf+inf -inf-inf NaNNaN
    -inf-inf -inf-inf +inf+inf NaNNaN NaNNaN -inf-inf +inf+inf NaNNaN
    NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN
  • 십진 곱하기:Decimal multiplication:

    decimal operator *(decimal x, decimal y);
    

    결과 값이 너무 커서 @no__t 0 형식으로 나타낼 수 없는 경우 System.OverflowException이 throw 됩니다.If the resulting value is too large to represent in the decimal format, a System.OverflowException is thrown. 결과 값이 너무 작아서 @no__t 0 형식으로 나타낼 수 없는 경우 결과는 0입니다.If the result value is too small to represent in the decimal format, the result is zero. 반올림 전 결과의 배율은 두 피연산자의 눈금에 대 한 합계입니다.The scale of the result, before any rounding, is the sum of the scales of the two operands.

    소수점 곱셈은 System.Decimal 형식의 곱하기 연산자를 사용 하는 것과 같습니다.Decimal multiplication is equivalent to using the multiplication operator of type System.Decimal.

나누기 연산자Division operator

@No__t-0 형식의 작업에 대해 이항 연산자 오버 로드 확인 (이진 연산자 오버 로드 확인)이 적용 되어 특정 연산자 구현을 선택 합니다.For an operation of the form x / y, binary operator overload resolution (Binary operator overload resolution) is applied to select a specific operator implementation. 피연산자는 선택한 연산자의 매개 변수 형식으로 변환 되 고 결과의 형식은 연산자의 반환 형식입니다.The operands are converted to the parameter types of the selected operator, and the type of the result is the return type of the operator.

미리 정의 된 나누기 연산자는 아래에 나열 되어 있습니다.The predefined division operators are listed below. 연산자는 모두 xy의 몫을 계산 합니다.The operators all compute the quotient of x and y.

  • 정수 나누기:Integer division:

    int operator /(int x, int y);
    uint operator /(uint x, uint y);
    long operator /(long x, long y);
    ulong operator /(ulong x, ulong y);
    

    오른쪽 피연산자의 값이 0 이면 System.DivideByZeroException이 throw 됩니다.If the value of the right operand is zero, a System.DivideByZeroException is thrown.

    나누기는 결과를 0으로 반올림 합니다.The division rounds the result towards zero. 따라서 결과의 절대값은 두 피연산자 몫의 절대 값 보다 작거나 같은 가능한 가장 큰 정수입니다.Thus the absolute value of the result is the largest possible integer that is less than or equal to the absolute value of the quotient of the two operands. 두 피연산자의 부호가 같고 부호가 0 이거나 음수인 경우 결과는 0 또는 양수입니다.The result is zero or positive when the two operands have the same sign and zero or negative when the two operands have opposite signs.

    왼쪽 피연산자가 표현할 수 있는 가장 작은 값 int 또는 long 값이 고 오른쪽 피연산자가 -1 이면 오버플로가 발생 합니다.If the left operand is the smallest representable int or long value and the right operand is -1, an overflow occurs. @No__t-0 컨텍스트에서 System.ArithmeticException (또는 그 하위 클래스가 throw 됨)이 발생 합니다.In a checked context, this causes a System.ArithmeticException (or a subclass thereof) to be thrown. @No__t-0 컨텍스트에서 System.ArithmeticException 또는 해당 하위 클래스가 throw 되었는지 아니면 오버플로를 왼쪽 피연산자의 결과 값과 함께 보고 되지 않은로 정의 합니다.In an unchecked context, it is implementation-defined as to whether a System.ArithmeticException (or a subclass thereof) is thrown or the overflow goes unreported with the resulting value being that of the left operand.

  • 부동 소수점 나누기:Floating-point division:

    float operator /(float x, float y);
    double operator /(double x, double y);
    

    몫은 IEEE 754 산술의 규칙에 따라 계산 됩니다.The quotient is computed according to the rules of IEEE 754 arithmetic. 다음 표에서는 0이 아닌 유한 값, 0, 무한대 및 NaN의 모든 가능한 조합에 대 한 결과를 보여 줍니다.The following table lists the results of all possible combinations of nonzero finite values, zeros, infinities, and NaN's. 표에서 xy은 양의 유한 값입니다.In the table, x and y are positive finite values. zx / y의 결과입니다.z is the result of x / y. 결과가 너무 커서 대상 형식에 맞지 않는 경우 z은 무한대입니다.If the result is too large for the destination type, z is infinity. 대상 유형에 대 한 결과가 너무 작은 경우 z이 0입니다.If the result is too small for the destination type, z is zero.

    + y+y -y-y +0+0 -0-0 +inf+inf -inf-inf NaNNaN
    +x+x +z+z -z-z +inf+inf -inf-inf +0+0 -0-0 NaNNaN
    -x-x -z-z +z+z -inf-inf +inf+inf -0-0 +0+0 NaNNaN
    +0+0 +0+0 -0-0 NaNNaN NaNNaN +0+0 -0-0 NaNNaN
    -0-0 -0-0 +0+0 NaNNaN NaNNaN -0-0 +0+0 NaNNaN
    +inf+inf +inf+inf -inf-inf +inf+inf -inf-inf NaNNaN NaNNaN NaNNaN
    -inf-inf -inf-inf +inf+inf -inf-inf +inf+inf NaNNaN NaNNaN NaNNaN
    NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN
  • 소수 구분:Decimal division:

    decimal operator /(decimal x, decimal y);
    

    오른쪽 피연산자의 값이 0 이면 System.DivideByZeroException이 throw 됩니다.If the value of the right operand is zero, a System.DivideByZeroException is thrown. 결과 값이 너무 커서 @no__t 0 형식으로 나타낼 수 없는 경우 System.OverflowException이 throw 됩니다.If the resulting value is too large to represent in the decimal format, a System.OverflowException is thrown. 결과 값이 너무 작아서 @no__t 0 형식으로 나타낼 수 없는 경우 결과는 0입니다.If the result value is too small to represent in the decimal format, the result is zero. 결과의 소수 자릿수는 가장 가까운 표현 가능한 10 진수 값과 동일한 결과를 진정한 수학적 결과에 유지 하는 가장 작은 배율입니다.The scale of the result is the smallest scale that will preserve a result equal to the nearest representable decimal value to the true mathematical result.

    소수 나누기는 System.Decimal 형식의 나누기 연산자를 사용 하는 것과 같습니다.Decimal division is equivalent to using the division operator of type System.Decimal.

나머지 연산자Remainder operator

@No__t-0 형식의 작업에 대해 이항 연산자 오버 로드 확인 (이진 연산자 오버 로드 확인)이 적용 되어 특정 연산자 구현을 선택 합니다.For an operation of the form x % y, binary operator overload resolution (Binary operator overload resolution) is applied to select a specific operator implementation. 피연산자는 선택한 연산자의 매개 변수 형식으로 변환 되 고 결과의 형식은 연산자의 반환 형식입니다.The operands are converted to the parameter types of the selected operator, and the type of the result is the return type of the operator.

미리 정의 된 나머지 연산자는 아래에 나열 되어 있습니다.The predefined remainder operators are listed below. 연산자는 xy 사이의 나누기의 나머지를 계산 합니다.The operators all compute the remainder of the division between x and y.

  • 정수 나머지가:Integer remainder:

    int operator %(int x, int y);
    uint operator %(uint x, uint y);
    long operator %(long x, long y);
    ulong operator %(ulong x, ulong y);
    

    @No__t-0의 결과는-1 @no__t에 의해 생성 된 값입니다.The result of x % y is the value produced by x - (x / y) * y. @No__t-0이 0 이면 System.DivideByZeroException이 throw 됩니다.If y is zero, a System.DivideByZeroException is thrown.

    왼쪽 피연산자가 가장 작은 @no__t 0 또는 long 값이 고 오른쪽 피연산자가 -1 이면 System.OverflowException이 throw 됩니다.If the left operand is the smallest int or long value and the right operand is -1, a System.OverflowException is thrown. 경우에 x % y x / y에서 예외를 throw 하지 않는 예외를 throw 합니다.In no case does x % y throw an exception where x / y would not throw an exception.

  • 부동 소수점 나머지:Floating-point remainder:

    float operator %(float x, float y);
    double operator %(double x, double y);
    

    다음 표에서는 0이 아닌 유한 값, 0, 무한대 및 NaN의 모든 가능한 조합에 대 한 결과를 보여 줍니다.The following table lists the results of all possible combinations of nonzero finite values, zeros, infinities, and NaN's. 표에서 xy은 양의 유한 값입니다.In the table, x and y are positive finite values. zx % y의 결과 이며 x - n * y로 계산 됩니다. 여기서 nx / y 보다 작거나 같은 가장 큰 정수입니다.z is the result of x % y and is computed as x - n * y, where n is the largest possible integer that is less than or equal to x / y. 나머지를 계산 하는이 메서드는 정수 피연산자에 사용 되는 것과 유사 하지만 IEEE 754 정의와는 다릅니다. nx / y과 가장 가까운 정수입니다.This method of computing the remainder is analogous to that used for integer operands, but differs from the IEEE 754 definition (in which n is the integer closest to x / y).

    + y+y -y-y +0+0 -0-0 +inf+inf -inf-inf NaNNaN
    +x+x +z+z +z+z NaNNaN NaNNaN xx xx NaNNaN
    -x-x -z-z -z-z NaNNaN NaNNaN -x-x -x-x NaNNaN
    +0+0 +0+0 +0+0 NaNNaN NaNNaN +0+0 +0+0 NaNNaN
    -0-0 -0-0 -0-0 NaNNaN NaNNaN -0-0 -0-0 NaNNaN
    +inf+inf NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN
    -inf-inf NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN
    NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN
  • 소수 나머지:Decimal remainder:

    decimal operator %(decimal x, decimal y);
    

    오른쪽 피연산자의 값이 0 이면 System.DivideByZeroException이 throw 됩니다.If the value of the right operand is zero, a System.DivideByZeroException is thrown. 반올림 전 결과의 소수 자릿수는 두 피연산자의 소수 자릿수 보다 크고 결과의 부호 (0이 아닌 경우)는 x의 부호와 동일 합니다.The scale of the result, before any rounding, is the larger of the scales of the two operands, and the sign of the result, if non-zero, is the same as that of x.

    소수 나머지는 System.Decimal 형식의 나머지 연산자를 사용 하는 것과 같습니다.Decimal remainder is equivalent to using the remainder operator of type System.Decimal.

더하기 연산자Addition operator

@No__t-0 형식의 작업에 대해 이항 연산자 오버 로드 확인 (이진 연산자 오버 로드 확인)이 적용 되어 특정 연산자 구현을 선택 합니다.For an operation of the form x + y, binary operator overload resolution (Binary operator overload resolution) is applied to select a specific operator implementation. 피연산자는 선택한 연산자의 매개 변수 형식으로 변환 되 고 결과의 형식은 연산자의 반환 형식입니다.The operands are converted to the parameter types of the selected operator, and the type of the result is the return type of the operator.

미리 정의 된 추가 연산자는 아래에 나열 되어 있습니다.The predefined addition operators are listed below. 숫자 및 열거형 형식의 경우 미리 정의 된 더하기 연산자는 두 피연산자의 합계를 계산 합니다.For numeric and enumeration types, the predefined addition operators compute the sum of the two operands. 피연산자 중 하나 또는 둘 다가 문자열 형식인 경우 미리 정의 된 더하기 연산자는 피연산자의 문자열 표현을 연결 합니다.When one or both operands are of type string, the predefined addition operators concatenate the string representation of the operands.

  • 정수 더하기:Integer addition:

    int operator +(int x, int y);
    uint operator +(uint x, uint y);
    long operator +(long x, long y);
    ulong operator +(ulong x, ulong y);
    

    @No__t-0 컨텍스트에서 합계가 결과 형식의 범위를 벗어나면 System.OverflowException이 throw 됩니다.In a checked context, if the sum is outside the range of the result type, a System.OverflowException is thrown. @No__t-0 컨텍스트에서 오버플로는 보고 되지 않으며 결과 형식 범위 밖의 중요 한 상위 비트가 모두 삭제 됩니다.In an unchecked context, overflows are not reported and any significant high-order bits outside the range of the result type are discarded.

  • 부동 소수점 추가:Floating-point addition:

    float operator +(float x, float y);
    double operator +(double x, double y);
    

    합계는 IEEE 754 산술의 규칙에 따라 계산 됩니다.The sum is computed according to the rules of IEEE 754 arithmetic. 다음 표에서는 0이 아닌 유한 값, 0, 무한대 및 NaN의 모든 가능한 조합에 대 한 결과를 보여 줍니다.The following table lists the results of all possible combinations of nonzero finite values, zeros, infinities, and NaN's. 테이블에서 xy은 0이 아닌 유한 값이 고, zx + y의 결과입니다.In the table, x and y are nonzero finite values, and z is the result of x + y. @No__t-0과 y의 크기가 같지만 부호가 같으면-2 @no__t는 양의 0입니다.If x and y have the same magnitude but opposite signs, z is positive zero. @No__t-0이 너무 커서 대상 @no__t 형식에 나타낼 수 없는 경우-1은 x + y와 같은 부호가 있는 무한대입니다.If x + y is too large to represent in the destination type, z is an infinity with the same sign as x + y.

    yy +0+0 -0-0 +inf+inf -inf-inf NaNNaN
    xx zz xx xx +inf+inf -inf-inf NaNNaN
    +0+0 yy +0+0 +0+0 +inf+inf -inf-inf NaNNaN
    -0-0 yy +0+0 -0-0 +inf+inf -inf-inf NaNNaN
    +inf+inf +inf+inf +inf+inf +inf+inf +inf+inf NaNNaN NaNNaN
    -inf-inf -inf-inf -inf-inf -inf-inf NaNNaN -inf-inf NaNNaN
    NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN
  • 10 진수 더하기:Decimal addition:

    decimal operator +(decimal x, decimal y);
    

    결과 값이 너무 커서 @no__t 0 형식으로 나타낼 수 없는 경우 System.OverflowException이 throw 됩니다.If the resulting value is too large to represent in the decimal format, a System.OverflowException is thrown. 반올림 전 결과의 소수 자릿수는 두 피연산자의 배율 보다 큽니다.The scale of the result, before any rounding, is the larger of the scales of the two operands.

    Decimal 더하기는 System.Decimal 형식의 더하기 연산자를 사용 하는 것과 같습니다.Decimal addition is equivalent to using the addition operator of type System.Decimal.

  • 열거형 추가.Enumeration addition. 모든 열거형 형식은 다음과 같이 미리 정의 된 연산자를 암시적으로 제공 합니다. 여기서 E은 열거형 형식이 고 UE의 기본 형식입니다.Every enumeration type implicitly provides the following predefined operators, where E is the enum type, and U is the underlying type of E:

    E operator +(E x, U y);
    E operator +(U x, E y);
    

    런타임에 이러한 연산자는 (E)((U)x + (U)y)으로 정확 하 게 계산 됩니다.At run-time these operators are evaluated exactly as (E)((U)x + (U)y).

  • 문자열 연결:String concatenation:

    string operator +(string x, string y);
    string operator +(string x, object y);
    string operator +(object x, string y);
    

    이항 + 연산자의 이러한 오버 로드는 문자열 연결을 수행 합니다.These overloads of the binary + operator perform string concatenation. 문자열 연결의 피연산자가 0 @no__t 이면 빈 문자열이 대체 됩니다.If an operand of string concatenation is null, an empty string is substituted. 그렇지 않으면-1 @no__t 형식에서 상속 된 가상 ToString 메서드를 호출 하 여 문자열이 아닌 모든 인수를 해당 문자열 표현으로 변환 합니다.Otherwise, any non-string argument is converted to its string representation by invoking the virtual ToString method inherited from type object. @No__t-0 null을 반환 하면 빈 문자열이 대체 됩니다.If ToString returns null, an empty string is substituted.

    using System;
    
    class Test
    {
        static void Main() {
            string s = null;
            Console.WriteLine("s = >" + s + "<");        // displays s = ><
            int i = 1;
            Console.WriteLine("i = " + i);               // displays i = 1
            float f = 1.2300E+15F;
            Console.WriteLine("f = " + f);               // displays f = 1.23E+15
            decimal d = 2.900m;
            Console.WriteLine("d = " + d);               // displays d = 2.900
        }
    }
    

    문자열 연결 연산자의 결과는 왼쪽 피연산자의 문자 다음에 오른쪽 피연산자의 문자로 구성 된 문자열입니다. 문자열 연결 연산자는 null 값을 반환 하지 않습니다. 결과 문자열을 할당 하는 데 사용할 수 있는 메모리가 충분 하지 않은 경우 System.OutOfMemoryException이 throw 될 수 있습니다.A System.OutOfMemoryException may be thrown if there is not enough memory available to allocate the resulting string.

  • 대리자 조합입니다.Delegate combination. 모든 대리자 형식은 다음과 같이 미리 정의 된 연산자를 암시적으로 제공 합니다. 여기서 D은 대리자 형식입니다.Every delegate type implicitly provides the following predefined operator, where D is the delegate type:

    D operator +(D x, D y);
    

    이항 + 연산자는 두 피연산자의 대리자 형식이 모두-1 @no__t 경우 대리자 조합을 수행 합니다.The binary + operator performs delegate combination when both operands are of some delegate type D. 피연산자에 다른 대리자 형식이 있으면 바인딩 시간 오류가 발생 합니다. 첫 번째 피연산자가 0 @no__t 이면 작업의 결과는 두 번째 피연산자의 값이 고, 그렇지 @no__t 않은 경우에도-1입니다.(If the operands have different delegate types, a binding-time error occurs.) If the first operand is null, the result of the operation is the value of the second operand (even if that is also null). 그렇지 않고 두 번째 피연산자가 0 @no__t 경우 연산의 결과는 첫 번째 피연산자의 값입니다.Otherwise, if the second operand is null, then the result of the operation is the value of the first operand. 그렇지 않은 경우 작업의 결과는 호출 될 때 첫 번째 피연산자를 호출 하 고 두 번째 피연산자를 호출 하는 새 대리자 인스턴스입니다.Otherwise, the result of the operation is a new delegate instance that, when invoked, invokes the first operand and then invokes the second operand. 대리자 조합의 예는 빼기 연산자대리자 호출을 참조 하세요.For examples of delegate combination, see Subtraction operator and Delegate invocation. @No__t-0은 대리자 형식이 아니기 때문에 operator @ no__t-2이 (가) 정의 되지 않았습니다.Since System.Delegate is not a delegate type, operator + is not defined for it.

빼기 연산자Subtraction operator

@No__t-0 형식의 작업에 대해 이항 연산자 오버 로드 확인 (이진 연산자 오버 로드 확인)이 적용 되어 특정 연산자 구현을 선택 합니다.For an operation of the form x - y, binary operator overload resolution (Binary operator overload resolution) is applied to select a specific operator implementation. 피연산자는 선택한 연산자의 매개 변수 형식으로 변환 되 고 결과의 형식은 연산자의 반환 형식입니다.The operands are converted to the parameter types of the selected operator, and the type of the result is the return type of the operator.

미리 정의 된 빼기 연산자는 아래에 나열 되어 있습니다.The predefined subtraction operators are listed below. 연산자는 모두 x에서 y을 뺍니다.The operators all subtract y from x.

  • 정수 빼기:Integer subtraction:

    int operator -(int x, int y);
    uint operator -(uint x, uint y);
    long operator -(long x, long y);
    ulong operator -(ulong x, ulong y);
    

    @No__t-0 컨텍스트에서 차이가 결과 형식의 범위를 벗어나면 System.OverflowException이 throw 됩니다.In a checked context, if the difference is outside the range of the result type, a System.OverflowException is thrown. @No__t-0 컨텍스트에서 오버플로는 보고 되지 않으며 결과 형식 범위 밖의 중요 한 상위 비트가 모두 삭제 됩니다.In an unchecked context, overflows are not reported and any significant high-order bits outside the range of the result type are discarded.

  • 부동 소수점 빼기:Floating-point subtraction:

    float operator -(float x, float y);
    double operator -(double x, double y);
    

    차이점은 IEEE 754 산술의 규칙에 따라 계산 됩니다.The difference is computed according to the rules of IEEE 754 arithmetic. 다음 표에서는 0이 아닌 유한 값, 0, 무한대 및 Nan의 가능한 모든 조합에 대 한 결과를 보여 줍니다.The following table lists the results of all possible combinations of nonzero finite values, zeros, infinities, and NaNs. 테이블에서 xy은 0이 아닌 유한 값이 고, zx - y의 결과입니다.In the table, x and y are nonzero finite values, and z is the result of x - y. @No__t-0과 y이 같으면-2 @no__t는 양의 0입니다.If x and y are equal, z is positive zero. @No__t-0이 너무 커서 대상 @no__t 형식에 나타낼 수 없는 경우-1은 x - y와 같은 부호가 있는 무한대입니다.If x - y is too large to represent in the destination type, z is an infinity with the same sign as x - y.

    yy +0+0 -0-0 +inf+inf -inf-inf NaNNaN
    xx zz xx xx -inf-inf +inf+inf NaNNaN
    +0+0 -y-y +0+0 +0+0 -inf-inf +inf+inf NaNNaN
    -0-0 -y-y -0-0 +0+0 -inf-inf +inf+inf NaNNaN
    +inf+inf +inf+inf +inf+inf +inf+inf NaNNaN +inf+inf NaNNaN
    -inf-inf -inf-inf -inf-inf -inf-inf -inf-inf NaNNaN NaNNaN
    NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN
  • 소수 빼기:Decimal subtraction:

    decimal operator -(decimal x, decimal y);
    

    결과 값이 너무 커서 @no__t 0 형식으로 나타낼 수 없는 경우 System.OverflowException이 throw 됩니다.If the resulting value is too large to represent in the decimal format, a System.OverflowException is thrown. 반올림 전 결과의 소수 자릿수는 두 피연산자의 배율 보다 큽니다.The scale of the result, before any rounding, is the larger of the scales of the two operands.

    10 진수 빼기는 System.Decimal 형식의 빼기 연산자를 사용 하는 것과 같습니다.Decimal subtraction is equivalent to using the subtraction operator of type System.Decimal.

  • 열거형 빼기입니다.Enumeration subtraction. 모든 열거형 형식은 다음과 같이 미리 정의 된 연산자를 암시적으로 제공 합니다. 여기서 E은 열거형 형식이 고 UE의 기본 형식입니다.Every enumeration type implicitly provides the following predefined operator, where E is the enum type, and U is the underlying type of E:

    U operator -(E x, E y);
    

    이 연산자는 (U)((U)x - (U)y)으로 정확 하 게 계산 됩니다.This operator is evaluated exactly as (U)((U)x - (U)y). 즉, 연산자는 xy의 서 수 값 간의 차이를 계산 하며 결과의 형식은 열거형의 기본 형식입니다.In other words, the operator computes the difference between the ordinal values of x and y, and the type of the result is the underlying type of the enumeration.

    E operator -(E x, U y);
    

    이 연산자는 (E)((U)x - y)으로 정확 하 게 계산 됩니다.This operator is evaluated exactly as (E)((U)x - y). 즉, 연산자는 열거형의 내부 형식에서 값을 빼서 열거형의 값을 생성 합니다.In other words, the operator subtracts a value from the underlying type of the enumeration, yielding a value of the enumeration.

  • 대리자 제거.Delegate removal. 모든 대리자 형식은 다음과 같이 미리 정의 된 연산자를 암시적으로 제공 합니다. 여기서 D은 대리자 형식입니다.Every delegate type implicitly provides the following predefined operator, where D is the delegate type:

    D operator -(D x, D y);
    

    이항 - 연산자는 두 피연산자의 대리자 형식이 모두-1 @no__t 경우 대리자 제거를 수행 합니다.The binary - operator performs delegate removal when both operands are of some delegate type D. 피연산자에 다른 대리자 형식이 있으면 바인딩 시간 오류가 발생 합니다.If the operands have different delegate types, a binding-time error occurs. 첫 번째 피연산자가 null이면, 작업의 결과는 null입니다.If the first operand is null, the result of the operation is null. 그렇지 않고 두 번째 피연산자가 0 @no__t 경우 연산의 결과는 첫 번째 피연산자의 값입니다.Otherwise, if the second operand is null, then the result of the operation is the value of the first operand. 그렇지 않으면 두 피연산자 모두 하나 이상의 항목을 포함 하는 호출 목록 (대리자 선언)을 나타내며, 두 번째 피연산자의 항목이 제거 된 첫 번째 피연산자의 목록으로 구성 된 새 호출 목록이 생성 됩니다. 피연산자 목록은 첫 번째의 가장 인접 한 하위 목록입니다.Otherwise, both operands represent invocation lists (Delegate declarations) having one or more entries, and the result is a new invocation list consisting of the first operand's list with the second operand's entries removed from it, provided the second operand's list is a proper contiguous sublist of the first's. 하위 목록 같음을 결정 하기 위해 해당 항목은 대리자 같음 연산자 (대리자 같음 연산자)의 경우와 비교 됩니다. 그렇지 않으면 결과는 왼쪽 피연산자의 값입니다.(To determine sublist equality, corresponding entries are compared as for the delegate equality operator (Delegate equality operators).) Otherwise, the result is the value of the left operand. 프로세스에서 피연산자 목록 중 어느 것도 변경 되지 않습니다.Neither of the operands' lists is changed in the process. 두 번째 피연산자의 목록이 첫 번째 피연산자의 목록에서 연속 항목의 여러 sublists 일치 하는 경우 인접 한 항목의 가장 일치 하는 하위 목록이 제거 됩니다.If the second operand's list matches multiple sublists of contiguous entries in the first operand's list, the right-most matching sublist of contiguous entries is removed. 제거로 인해 빈 목록이 생성되면 결과는 null입니다.If removal results in an empty list, the result is null. 예를 들어 다음과 같은 가치를 제공해야 합니다.For example:

    delegate void D(int x);
    
    class C
    {
        public static void M1(int i) { /* ... */ }
        public static void M2(int i) { /* ... */ }
    }
    
    class Test
    {
        static void Main() { 
            D cd1 = new D(C.M1);
            D cd2 = new D(C.M2);
            D cd3 = cd1 + cd2 + cd2 + cd1;   // M1 + M2 + M2 + M1
            cd3 -= cd1;                      // => M1 + M2 + M2
    
            cd3 = cd1 + cd2 + cd2 + cd1;     // M1 + M2 + M2 + M1
            cd3 -= cd1 + cd2;                // => M2 + M1
    
            cd3 = cd1 + cd2 + cd2 + cd1;     // M1 + M2 + M2 + M1
            cd3 -= cd2 + cd2;                // => M1 + M1
    
            cd3 = cd1 + cd2 + cd2 + cd1;     // M1 + M2 + M2 + M1
            cd3 -= cd2 + cd1;                // => M1 + M2
    
            cd3 = cd1 + cd2 + cd2 + cd1;     // M1 + M2 + M2 + M1
            cd3 -= cd1 + cd1;                // => M1 + M2 + M2 + M1
        }
    }
    

시프트 연산자Shift operators

@No__t-0 및 >> 연산자를 사용 하 여 비트 시프트 연산을 수행 합니다.The << and >> operators are used to perform bit shifting operations.

shift_expression
    : additive_expression
    | shift_expression '<<' additive_expression
    | shift_expression right_shift additive_expression
    ;

Shift_expression 의 피연산자가 컴파일 타임 형식 dynamic 이면 식이 동적으로 바인딩됩니다 (동적 바인딩).If an operand of a shift_expression has the compile-time type dynamic, then the expression is dynamically bound (Dynamic binding). 이 경우 식의 컴파일 시간 형식은 dynamic 이며 아래에 설명 된 해결 방법은 컴파일 시간 @no__t 형식이-1 인 피연산자의 런타임 형식을 사용 하 여 런타임에 수행 됩니다.In this case the compile-time type of the expression is dynamic, and the resolution described below will take place at run-time using the run-time type of those operands that have the compile-time type dynamic.

@No__t-0 또는 x >> count 형식의 작업에 대해 이항 연산자 오버 로드 확인 (이진 연산자 오버 로드 확인)이 적용 되어 특정 연산자 구현을 선택 합니다.For an operation of the form x << count or x >> count, binary operator overload resolution (Binary operator overload resolution) is applied to select a specific operator implementation. 피연산자는 선택한 연산자의 매개 변수 형식으로 변환 되 고 결과의 형식은 연산자의 반환 형식입니다.The operands are converted to the parameter types of the selected operator, and the type of the result is the return type of the operator.

오버 로드 된 시프트 연산자를 선언 하는 경우 첫 번째 피연산자의 형식은 항상 연산자 선언을 포함 하는 클래스 또는 구조체 여야 하 고 두 번째 피연산자의 형식은 항상 0 @no__t 이어야 합니다.When declaring an overloaded shift operator, the type of the first operand must always be the class or struct containing the operator declaration, and the type of the second operand must always be int.

미리 정의 된 시프트 연산자는 아래에 나열 되어 있습니다.The predefined shift operators are listed below.

  • 왼쪽으로 이동:Shift left:

    int operator <<(int x, int count);
    uint operator <<(uint x, int count);
    long operator <<(long x, int count);
    ulong operator <<(ulong x, int count);
    

    @No__t-0 연산자는 아래에 설명 된 대로 계산 된 비트 수 만큼 x을 이동 합니다.The << operator shifts x left by a number of bits computed as described below.

    @No__t-0의 결과 형식 범위를 벗어난 상위 비트는 무시 되 고 나머지 비트가 왼쪽으로 이동 하며, 하위 순서 빈 비트 위치는 0으로 설정 됩니다.The high-order bits outside the range of the result type of x are discarded, the remaining bits are shifted left, and the low-order empty bit positions are set to zero.

  • 오른쪽으로 이동:Shift right:

    int operator >>(int x, int count);
    uint operator >>(uint x, int count);
    long operator >>(long x, int count);
    ulong operator >>(ulong x, int count);
    

    @No__t-0 연산자는 아래에 설명 된 대로 계산 된 비트 수 만큼 x을 이동 합니다.The >> operator shifts x right by a number of bits computed as described below.

    @No__t-0이 int 또는 long 형식인 경우 x의 하위 비트가 삭제 되 고 나머지 비트가 오른쪽으로 이동 하며, x가 음수가 아닌 경우에는 0으로 설정 되 고, x가 음수인 경우에는 1로 설정 됩니다.When x is of type int or long, the low-order bits of x are discarded, the remaining bits are shifted right, and the high-order empty bit positions are set to zero if x is non-negative and set to one if x is negative.

    @No__t-0이 uint 또는 ulong 형식이 면-3 @no__t의 하위 비트가 삭제 되 고 나머지 비트가 오른쪽으로 이동 하며, 상위 순서 빈 비트 위치는 0으로 설정 됩니다.When x is of type uint or ulong, the low-order bits of x are discarded, the remaining bits are shifted right, and the high-order empty bit positions are set to zero.

미리 정의 된 연산자의 경우 이동할 비트 수는 다음과 같이 계산 됩니다.For the predefined operators, the number of bits to shift is computed as follows:

  • @No__t-0 형식이 int 또는 uint 인 경우 시프트 횟수는 count의 하위 5 비트로 지정 됩니다.When the type of x is int or uint, the shift count is given by the low-order five bits of count. 즉, 시프트 횟수는 count & 0x1F에서 계산 됩니다.In other words, the shift count is computed from count & 0x1F.
  • @No__t-0 형식이 long 또는 ulong 인 경우 시프트 횟수는 count의 하위 6 비트로 지정 됩니다.When the type of x is long or ulong, the shift count is given by the low-order six bits of count. 즉, 시프트 횟수는 count & 0x3F에서 계산 됩니다.In other words, the shift count is computed from count & 0x3F.

결과 시프트 횟수가 0 이면 시프트 연산자는 @no__t 값을 반환 합니다.If the resulting shift count is zero, the shift operators simply return the value of x.

시프트 연산은 오버플로를 일으키지 않으며 checkedunchecked 컨텍스트에서 동일한 결과를 생성 합니다.Shift operations never cause overflows and produce the same results in checked and unchecked contexts.

@No__t-0 연산자의 왼쪽 피연산자가 부호 있는 정수 형식이 면 연산자는 피연산자의 가장 중요 한 비트 (부호 비트) 값이 상위 빈 비트 위치로 전파 되는 산술 시프트를 수행 합니다.When the left operand of the >> operator is of a signed integral type, the operator performs an arithmetic shift right wherein the value of the most significant bit (the sign bit) of the operand is propagated to the high-order empty bit positions. @No__t-0 연산자의 왼쪽 피연산자가 부호 없는 정수 계열 형식인 경우 연산자는 높은 순서 빈 비트 위치를 항상 0으로 설정 하는 논리적 시프트를 수행 합니다.When the left operand of the >> operator is of an unsigned integral type, the operator performs a logical shift right wherein high-order empty bit positions are always set to zero. 피연산자 형식에서 유추 된의 반대 연산을 수행 하려면 명시적 캐스트를 사용할 수 있습니다.To perform the opposite operation of that inferred from the operand type, explicit casts can be used. 예를 들어 xint 형식의 변수인 경우-2 unchecked((int)((uint)x >> y))x의 논리적 이동을 수행 합니다.For example, if x is a variable of type int, the operation unchecked((int)((uint)x >> y)) performs a logical shift right of x.

관계형 및 형식 테스트 연산자Relational and type-testing operators

@No__t-0, !=, <, >, <=, >=, as 연산자를 관계형 및 형식 테스트 연산자 라고 합니다.The ==, !=, <, >, <=, >=, is and as operators are called the relational and type-testing operators.

relational_expression
    : shift_expression
    | relational_expression '<' shift_expression
    | relational_expression '>' shift_expression
    | relational_expression '<=' shift_expression
    | relational_expression '>=' shift_expression
    | relational_expression 'is' type
    | relational_expression 'as' type
    ;

equality_expression
    : relational_expression
    | equality_expression '==' relational_expression
    | equality_expression '!=' relational_expression
    ;

@No__t-0 연산자는 is 연산자 에 설명 되어 있으며 as 연산자는 as 연산자에 설명 되어 있습니다.The is operator is described in The is operator and the as operator is described in The as operator.

@No__t-0, !=, <, >, <= 및 @no__t 연산자는 비교 연산자입니다.The ==, !=, <, >, <= and >= operators are comparison operators.

비교 연산자의 피연산자에 컴파일 타임 형식 dynamic이 있으면 식이 동적으로 바인딩됩니다 (동적 바인딩).If an operand of a comparison operator has the compile-time type dynamic, then the expression is dynamically bound (Dynamic binding). 이 경우 식의 컴파일 시간 형식은 dynamic 이며 아래에 설명 된 해결 방법은 컴파일 시간 @no__t 형식이-1 인 피연산자의 런타임 형식을 사용 하 여 런타임에 수행 됩니다.In this case the compile-time type of the expression is dynamic, and the resolution described below will take place at run-time using the run-time type of those operands that have the compile-time type dynamic.

@No__t-0 op y 형식의 작업에서 op 가 비교 연산자 인 경우 오버 로드 확인 (이진 연산자 오버 로드 확인)이 적용 되어 특정 연산자 구현을 선택 합니다.For an operation of the form x op y, where op is a comparison operator, overload resolution (Binary operator overload resolution) is applied to select a specific operator implementation. 피연산자는 선택한 연산자의 매개 변수 형식으로 변환 되 고 결과의 형식은 연산자의 반환 형식입니다.The operands are converted to the parameter types of the selected operator, and the type of the result is the return type of the operator.

미리 정의 된 비교 연산자에 대해서는 다음 섹션에서 설명 합니다.The predefined comparison operators are described in the following sections. 미리 정의 된 모든 비교 연산자는 다음 표에 설명 된 대로 bool 형식의 결과를 반환 합니다.All predefined comparison operators return a result of type bool, as described in the following table.

연산Operation 결과Result
x == y x @no__t y와 같으면-3이 고 @no__t, 그렇지 않으면 0입니다.true if x is equal to y, false otherwise
x != y x @no__t y와 같지 않으면-3이 고 @no__t, 그렇지 않으면 0입니다.true if x is not equal to y, false otherwise
x < y x @no__t y 보다 작은 경우에는 0이 고 @no__t, 그렇지 않으면-3입니다.true if x is less than y, false otherwise
x > y x @no__t y 보다 크면-3이 고 @no__t, 그렇지 않으면 0입니다.true if x is greater than y, false otherwise
x <= y x @no__t y 보다 작거나 같으면-3이 고 @no__t, 그렇지 않으면 0입니다.true if x is less than or equal to y, false otherwise
x >= y x @no__t y 보다 크거나 같으면-3이 고 @no__t, 그렇지 않으면 0입니다.true if x is greater than or equal to y, false otherwise

정수 비교 연산자Integer comparison operators

미리 정의 된 정수 비교 연산자는 다음과 같습니다.The predefined integer comparison operators are:

bool operator ==(int x, int y);
bool operator ==(uint x, uint y);
bool operator ==(long x, long y);
bool operator ==(ulong x, ulong y);

bool operator !=(int x, int y);
bool operator !=(uint x, uint y);
bool operator !=(long x, long y);
bool operator !=(ulong x, ulong y);

bool operator <(int x, int y);
bool operator <(uint x, uint y);
bool operator <(long x, long y);
bool operator <(ulong x, ulong y);

bool operator >(int x, int y);
bool operator >(uint x, uint y);
bool operator >(long x, long y);
bool operator >(ulong x, ulong y);

bool operator <=(int x, int y);
bool operator <=(uint x, uint y);
bool operator <=(long x, long y);
bool operator <=(ulong x, ulong y);

bool operator >=(int x, int y);
bool operator >=(uint x, uint y);
bool operator >=(long x, long y);
bool operator >=(ulong x, ulong y);

이러한 각 연산자는 두 정수 피연산자의 숫자 값을 비교 하 고 특정 관계가 true 또는 false 인지 여부를 나타내는 bool 값을 반환 합니다.Each of these operators compares the numeric values of the two integer operands and returns a bool value that indicates whether the particular relation is true or false.

부동 소수점 비교 연산자Floating-point comparison operators

미리 정의 된 부동 소수점 비교 연산자는 다음과 같습니다.The predefined floating-point comparison operators are:

bool operator ==(float x, float y);
bool operator ==(double x, double y);

bool operator !=(float x, float y);
bool operator !=(double x, double y);

bool operator <(float x, float y);
bool operator <(double x, double y);

bool operator >(float x, float y);
bool operator >(double x, double y);

bool operator <=(float x, float y);
bool operator <=(double x, double y);

bool operator >=(float x, float y);
bool operator >=(double x, double y);

연산자는 IEEE 754 표준의 규칙에 따라 피연산자를 비교 합니다.The operators compare the operands according to the rules of the IEEE 754 standard:

  • 피연산자 중 하나가 NaN 이면 결과는-2 @no__t를 @no__t 제외한 모든 연산자에 대 한 false입니다.If either operand is NaN, the result is false for all operators except !=, for which the result is true. 두 피연산자의 경우 x != y은 항상 !(x == y)과 동일한 결과를 생성 합니다.For any two operands, x != y always produces the same result as !(x == y). 그러나 두 피연산자 중 하나 또는 둘 다 NaN 인 경우 <, >, <=>= 연산자는 반대 연산자의 논리 부정과 동일한 결과를 생성 하지 않습니다.However, when one or both operands are NaN, the <, >, <=, and >= operators do not produce the same results as the logical negation of the opposite operator. 예를 들어 xy 중 하나가 NaN 이면 x < y @no__t는-3 이지만 !(x >= y)true입니다.For example, if either of x and y is NaN, then x < y is false, but !(x >= y) is true.

  • 피연산자가 NaN이 아닌 경우 연산자는 순서와 관련 하 여 두 부동 소수점 피연산자의 값을 비교 합니다.When neither operand is NaN, the operators compare the values of the two floating-point operands with respect to the ordering

    -inf < -max < ... < -min < -0.0 == +0.0 < +min < ... < +max < +inf
    

    여기서 minmax은 지정 된 부동 소수점 형식으로 표현할 수 있는 가장 작은 양수 및 가장 큰 값입니다.where min and max are the smallest and largest positive finite values that can be represented in the given floating-point format. 이러한 순서 지정의 주목할 만한 효과는 다음과 같습니다.Notable effects of this ordering are:

    • 음수 및 양수 0은 동일한 것으로 간주 됩니다.Negative and positive zeros are considered equal.
    • 음의 무한대는 다른 모든 값 보다 작은 것으로 간주 되 고 다른 음의 무한대와 동일 하 게 간주 됩니다.A negative infinity is considered less than all other values, but equal to another negative infinity.
    • 양의 무한대는 다른 모든 값 보다 큰 것으로 간주 되지만 다른 양의 무한대와 동일 합니다.A positive infinity is considered greater than all other values, but equal to another positive infinity.

Decimal 비교 연산자Decimal comparison operators

미리 정의 된 10 진수 비교 연산자는 다음과 같습니다.The predefined decimal comparison operators are:

bool operator ==(decimal x, decimal y);
bool operator !=(decimal x, decimal y);
bool operator <(decimal x, decimal y);
bool operator >(decimal x, decimal y);
bool operator <=(decimal x, decimal y);
bool operator >=(decimal x, decimal y);

이러한 각 연산자는 두 개의 10 진수 피연산자의 숫자 값을 비교 하 고 특정 관계가 true 또는 false 인지 여부를 나타내는 bool 값을 반환 합니다.Each of these operators compares the numeric values of the two decimal operands and returns a bool value that indicates whether the particular relation is true or false. 각 소수 비교는 System.Decimal 형식의 해당 하는 관계형 연산자나 같음 연산자를 사용 하는 것과 같습니다.Each decimal comparison is equivalent to using the corresponding relational or equality operator of type System.Decimal.

부울 같음 연산자Boolean equality operators

미리 정의 된 부울 같음 연산자는 다음과 같습니다.The predefined boolean equality operators are:

bool operator ==(bool x, bool y);
bool operator !=(bool x, bool y);

@No__t-0은 xy이 모두 true 이거나 x와 @no__t 모두 @no__t 경우 true입니다.The result of == is true if both x and y are true or if both x and y are false. 그렇지 않으면 결과는 false입니다.Otherwise, the result is false.

@No__t-0은 xy이 모두 true 이거나 x와 @no__t 모두 @no__t 경우 false입니다.The result of != is false if both x and y are true or if both x and y are false. 그렇지 않으면 결과는 true입니다.Otherwise, the result is true. 피연산자의 형식이 bool 인 경우 != 연산자는 ^ 연산자와 동일한 결과를 생성 합니다.When the operands are of type bool, the != operator produces the same result as the ^ operator.

열거 비교 연산자Enumeration comparison operators

모든 열거형 형식은 다음과 같이 미리 정의 된 비교 연산자를 암시적으로 제공 합니다.Every enumeration type implicitly provides the following predefined comparison operators:

bool operator ==(E x, E y);
bool operator !=(E x, E y);
bool operator <(E x, E y);
bool operator >(E x, E y);
bool operator <=(E x, E y);
bool operator >=(E x, E y);

@No__t-@no__t 0을 평가한 결과-1과 @no__t-@no__t 2는 기본 형식이 U이 고 op는 비교 연산자 중 하나 이며 ((U)x) op ((U)y)을 평가 하는 것과 정확 하 게 동일 합니다.The result of evaluating x op y, where x and y are expressions of an enumeration type E with an underlying type U, and op is one of the comparison operators, is exactly the same as evaluating ((U)x) op ((U)y). 즉, 열거형 형식 비교 연산자는 두 피연산자의 기본 정수 값을 비교 합니다.In other words, the enumeration type comparison operators simply compare the underlying integral values of the two operands.

참조 형식 같음 연산자Reference type equality operators

미리 정의 된 참조 형식 같음 연산자는 다음과 같습니다.The predefined reference type equality operators are:

bool operator ==(object x, object y);
bool operator !=(object x, object y);

연산자는 두 참조의 같음 또는 같지 않음 비교 결과를 반환 합니다.The operators return the result of comparing the two references for equality or non-equality.

미리 정의 된 참조 형식 같음 연산자는 object 형식의 피연산자를 허용 하므로 해당 operator ==operator != 멤버를 선언 하지 않는 모든 형식에 적용 됩니다.Since the predefined reference type equality operators accept operands of type object, they apply to all types that do not declare applicable operator == and operator != members. 반대로, 적용 가능한 모든 사용자 정의 같음 연산자는 미리 정의 된 참조 형식 같음 연산자를 효과적으로 숨깁니다.Conversely, any applicable user-defined equality operators effectively hide the predefined reference type equality operators.

미리 정의 된 참조 형식 같음 연산자에는 다음 중 하나가 필요 합니다.The predefined reference type equality operators require one of the following:

  • 두 피연산자 모두 reference_type 또는 리터럴 null로 알려진 형식의 값입니다.Both operands are a value of a type known to be a reference_type or the literal null. 또한 피연산자의 형식에서 다른 피연산자의 형식으로의 명시적 참조 변환 (명시적 참조변환)이 있습니다.Furthermore, an explicit reference conversion (Explicit reference conversions) exists from the type of either operand to the type of the other operand.
  • 피연산자 하나는 T 형식의 값입니다. 여기서 Ttype_parameter 이 고 다른 피연산자는 리터럴 null입니다.One operand is a value of type T where T is a type_parameter and the other operand is the literal null. 또한 T에는 값 형식 제약 조건이 없습니다.Furthermore T does not have the value type constraint.

이러한 조건 중 하나가 true가 아니면 바인딩 타임 오류가 발생 합니다.Unless one of these conditions are true, a binding-time error occurs. 이러한 규칙의 주목할 만한 의미는 다음과 같습니다.Notable implications of these rules are:

  • 미리 정의 된 참조 형식 같음 연산자를 사용 하 여 바인딩 시간에 서로 다른 두 참조를 비교 하는 경우 바인딩 시간 오류가 발생 합니다.It is a binding-time error to use the predefined reference type equality operators to compare two references that are known to be different at binding-time. 예를 들어 피연산자의 바인딩 시간 형식이 두 개의 클래스 형식 AB 인 경우, 두 AB이 다른 형식에서 파생 되지 않는 경우 두 피연산자가 동일한 개체를 참조할 수 없습니다.For example, if the binding-time types of the operands are two class types A and B, and if neither A nor B derives from the other, then it would be impossible for the two operands to reference the same object. 따라서 작업은 바인딩 시간 오류로 간주 됩니다.Thus, the operation is considered a binding-time error.
  • 미리 정의 된 참조 형식 같음 연산자는 값 형식 피연산자를 비교할 수 없습니다.The predefined reference type equality operators do not permit value type operands to be compared. 따라서 구조체 형식이 고유한 같음 연산자를 선언 하지 않으면 해당 구조체 형식의 값을 비교할 수 없습니다.Therefore, unless a struct type declares its own equality operators, it is not possible to compare values of that struct type.
  • 미리 정의 된 참조 형식 같음 연산자는 해당 피연산자에 대해 boxing 작업이 발생 하지 않습니다.The predefined reference type equality operators never cause boxing operations to occur for their operands. 새로 할당 된 boxing 된 인스턴스에 대 한 참조는 다른 모든 참조와 반드시 다를 수 있으므로 이러한 boxing 작업을 수행 하는 것은 의미가 없습니다.It would be meaningless to perform such boxing operations, since references to the newly allocated boxed instances would necessarily differ from all other references.
  • 형식 매개 변수 형식의 피연산자 Tnull과 비교 하 고 T의 런타임 형식이 값 형식인 경우 비교 결과는-3 @no__t 됩니다.If an operand of a type parameter type T is compared to null, and the run-time type of T is a value type, the result of the comparison is false.

다음 예제에서는 제한 되지 않는 형식 매개 변수 형식의 인수가 0 @no__t 인지 여부를 확인 합니다.The following example checks whether an argument of an unconstrained type parameter type is null.

class C<T>
{
    void F(T x) {
        if (x == null) throw new ArgumentNullException();
        ...
    }
}

@No__t-1은 값 형식을 나타낼 수 @no__t 있지만,-3 @no__t 값 형식인 경우 결과는 단순히 false로 정의 되는 경우에도 허용 됩니다.The x == null construct is permitted even though T could represent a value type, and the result is simply defined to be false when T is a value type.

@No__t-0 또는 x != y 형식의 작업에 대해 해당 하는 operator == 또는 operator !=이 있는 경우 연산자 오버 로드 확인 (이진 연산자 오버 로드 확인) 규칙은 미리 정의 된 참조 형식 같음 대신 해당 연산자를 선택 합니다. 연산자.For an operation of the form x == y or x != y, if any applicable operator == or operator != exists, the operator overload resolution (Binary operator overload resolution) rules will select that operator instead of the predefined reference type equality operator. 그러나 피연산자 중 하나 또는 둘 다를 명시적으로 object 형식으로 캐스팅 하 여 미리 정의 된 참조 형식 같음 연산자를 선택할 수 있습니다.However, it is always possible to select the predefined reference type equality operator by explicitly casting one or both of the operands to type object. 예제The example

using System;

class Test
{
    static void Main() {
        string s = "Test";
        string t = string.Copy(s);
        Console.WriteLine(s == t);
        Console.WriteLine((object)s == t);
        Console.WriteLine(s == (object)t);
        Console.WriteLine((object)s == (object)t);
    }
}

는 출력을 생성합니다.produces the output

True
False
False
False

@No__t-0 및 t 변수는 같은 문자를 포함 하는 두 개의 @no__t 2 인스턴스를 참조 합니다.The s and t variables refer to two distinct string instances containing the same characters. 두 피연산자가 모두 @no__t 형식일 때 미리 정의 된 문자열 같음 연산자 (문자열 같음 연산자)가 선택 되었기 때문에 첫 번째 비교 @no__t는-0을 출력 합니다.The first comparison outputs True because the predefined string equality operator (String equality operators) is selected when both operands are of type string. 두 피연산자 중 하나 또는 둘 다가 1 @no__t 형식일 때 미리 정의 된 참조 형식 같음 연산자가 선택 되므로 나머지 비교는 모든 출력 False입니다.The remaining comparisons all output False because the predefined reference type equality operator is selected when one or both of the operands are of type object.

위의 기법은 값 형식에는 의미가 없습니다.Note that the above technique is not meaningful for value types. 예제The example

class Test
{
    static void Main() {
        int i = 123;
        int j = 123;
        System.Console.WriteLine((object)i == (object)j);
    }
}

캐스트는 boxed int 값의 두 개별 인스턴스에 대 한 참조를 만들기 때문에 False을 출력 합니다.outputs False because the casts create references to two separate instances of boxed int values.

문자열 같음 연산자String equality operators

미리 정의 된 문자열 같음 연산자는 다음과 같습니다.The predefined string equality operators are:

bool operator ==(string x, string y);
bool operator !=(string x, string y);

다음 중 하나에 해당 하는 경우 두 string 값은 동일한 것으로 간주 됩니다.Two string values are considered equal when one of the following is true:

  • 두 값은 모두 null입니다.Both values are null.
  • 두 값은 모두 문자 위치에 동일한 길이와 동일한 문자가 있는 문자열 인스턴스에 대 한 null이 아닌 참조입니다.Both values are non-null references to string instances that have identical lengths and identical characters in each character position.

문자열 같음 연산자는 문자열 참조가 아닌 문자열 값을 비교 합니다.The string equality operators compare string values rather than string references. 두 개의 개별 문자열 인스턴스에 정확히 동일한 문자 시퀀스가 포함 된 경우 문자열의 값은 동일 하지만 참조는 다릅니다.When two separate string instances contain the exact same sequence of characters, the values of the strings are equal, but the references are different. 참조 형식 같음 연산자에 설명 된 것 처럼 참조 형식 같음 연산자를 사용 하 여 문자열 값 대신 문자열 참조를 비교할 수 있습니다.As described in Reference type equality operators, the reference type equality operators can be used to compare string references instead of string values.

같음 연산자 대리자Delegate equality operators

모든 대리자 형식은 다음과 같이 미리 정의 된 비교 연산자를 암시적으로 제공 합니다.Every delegate type implicitly provides the following predefined comparison operators:

bool operator ==(System.Delegate x, System.Delegate y);
bool operator !=(System.Delegate x, System.Delegate y);

두 대리자 인스턴스는 다음과 같이 동일 하 게 간주 됩니다.Two delegate instances are considered equal as follows:

  • 대리자 인스턴스 중 하나가-0 @no__t 경우 @no__t 두 값이 모두-1 인 경우에만 동일 합니다.If either of the delegate instances is null, they are equal if and only if both are null.
  • 대리자의 런타임 형식이 서로 다른 경우에는 같지 않습니다.If the delegates have different run-time type they are never equal.
  • 대리자 인스턴스 모두에 호출 목록 (대리자 선언)이 있는 경우에는 해당 호출 목록의 길이가 동일 하 고 한 호출 목록의 각 항목이 해당 하는에 있는 해당 다른의 호출 목록에 순서 대로 입력 합니다.If both of the delegate instances have an invocation list (Delegate declarations), those instances are equal if and only if their invocation lists are the same length, and each entry in one's invocation list is equal (as defined below) to the corresponding entry, in order, in the other's invocation list.

다음 규칙은 호출 목록 항목의 같음 여부를 제어 합니다.The following rules govern the equality of invocation list entries:

  • 두 호출 목록 항목이 모두 동일한 정적 메서드를 참조 하는 경우 항목은 동일 합니다.If two invocation list entries both refer to the same static method then the entries are equal.
  • 두 호출 목록 항목이 동일한 대상 개체 (참조 같음 연산자에 의해 정의 됨)에서 동일한 비정적 메서드를 참조 하는 경우 해당 항목은 동일 합니다.If two invocation list entries both refer to the same non-static method on the same target object (as defined by the reference equality operators) then the entries are equal.
  • 동일 하 게 (비어 있을 수 있음) 캡처된 외부 변수 인스턴스 집합을 사용 하 여 의미 있는 동일한 anonymous_method_expressions 또는 lambda_expression의 평가에서 생성 된 호출 목록 항목은 다릅니다.Invocation list entries produced from evaluation of semantically identical anonymous_method_expressions or lambda_expressions with the same (possibly empty) set of captured outer variable instances are permitted (but not required) to be equal.

같음 연산자 및 nullEquality operators and null

작업에 대해 미리 정의 되거나 사용자 정의 연산자 (제거 되지 않음 또는 리프트 된 형식)가 없는 경우에도 ==!= 연산자는 피연산자 하나를 nullable 형식의 값으로 지정 하 고 다른 피연산자는 null 리터럴이 되도록 허용 합니다.The == and != operators permit one operand to be a value of a nullable type and the other to be the null literal, even if no predefined or user-defined operator (in unlifted or lifted form) exists for the operation.

다음 형식 중 하나에 해당 하는 작업의 경우For an operation of one of the forms

x == null
null == x
x != null
null != x

여기서 x은 nullable 형식의 식입니다. 연산자 오버 로드 확인 (이항 연산자 오버 로드 확인)이 적용 가능한 연산자를 찾지 못하면-3 @no__t의 HasValue 속성에서 결과가 대신 계산 됩니다.where x is an expression of a nullable type, if operator overload resolution (Binary operator overload resolution) fails to find an applicable operator, the result is instead computed from the HasValue property of x. 특히 처음 두 형태는 !x.HasValue으로 변환 되 고 마지막 두 형태는 x.HasValue로 변환 됩니다.Specifically, the first two forms are translated into !x.HasValue, and last two forms are translated into x.HasValue.

Is 연산자The is operator

@No__t-0 연산자는 개체의 런타임 형식이 지정 된 형식과 호환 되는지 여부를 동적으로 확인 하는 데 사용 됩니다.The is operator is used to dynamically check if the run-time type of an object is compatible with a given type. 작업 결과 E is T (E은 식이 고, T는 형식)입니다. 참조 변환, boxing 변환 또는 unboxing 변환에 의해 E이 형식 @no__t으로 성공적으로 변환 될 수 있는지 여부를 나타내는 부울 값입니다.The result of the operation E is T, where E is an expression and T is a type, is a boolean value indicating whether E can successfully be converted to type T by a reference conversion, a boxing conversion, or an unboxing conversion. 다음 작업은 형식 인수가 모든 형식 매개 변수에 대해 대체 된 후 다음과 같이 평가 됩니다.The operation is evaluated as follows, after type arguments have been substituted for all type parameters:

  • @No__t-0이 익명 함수 이면 컴파일 시간 오류가 발생 합니다.If E is an anonymous function, a compile-time error occurs
  • @No__t-0이 메서드 그룹 이거나 null 리터럴이어야 E 형식이 참조 형식 이거나 nullable 형식이 고 E의 값이 null 이면 결과는 false입니다.If E is a method group or the null literal, of if the type of E is a reference type or a nullable type and the value of E is null, the result is false.
  • 그렇지 않으면 D은 다음과 같이 E의 동적 유형을 나타냅니다.Otherwise, let D represent the dynamic type of E as follows:
    • @No__t의 형식이 참조 형식이 면-1 @no__t E 인 인스턴스 참조의 런타임 형식입니다.If the type of E is a reference type, D is the run-time type of the instance reference by E.
    • @No__t의 형식이 nullable @no__t 형식이 면-1은 해당 nullable 형식의 기본 형식입니다.If the type of E is a nullable type, D is the underlying type of that nullable type.
    • @No__t의 형식이 null을 허용 하지 않는 값 형식인 경우-1 @no__t E의 유형입니다.If the type of E is a non-nullable value type, D is the type of E.
  • 작업의 결과는 다음과 같이 DT에 따라 달라 집니다.The result of the operation depends on D and T as follows:
    • @No__t-0이 참조 형식이 면 DT가 같은 형식이 고, D이 동일한 형식이 고,-3이 참조 형식이 고 D에서 T로의 암시적 참조 변환이 있거나, D이 값 형식이 고 @no__t에서 boxing 변환 되는 경우 결과는 true입니다. T이 있습니다.If T is a reference type, the result is true if D and T are the same type, if D is a reference type and an implicit reference conversion from D to T exists, or if D is a value type and a boxing conversion from D to T exists.
    • @No__t-0이 nullable 형식이 면 DT의 기본 형식인 경우 결과는 true입니다.If T is a nullable type, the result is true if D is the underlying type of T.
    • @No__t-0이 null을 허용 하지 않는 값 형식인 경우-1과 T가 같은 유형인 @no__t 경우 결과는 true입니다.If T is a non-nullable value type, the result is true if D and T are the same type.
    • 그렇지 않으면 결과는 false입니다.Otherwise, the result is false.

사용자 정의 변환은 is 연산자에서 고려 되지 않습니다.Note that user defined conversions, are not considered by the is operator.

As 연산자The as operator

@No__t-0 연산자는 값을 지정 된 참조 형식 또는 nullable 형식으로 명시적으로 변환 하는 데 사용 됩니다.The as operator is used to explicitly convert a value to a given reference type or nullable type. 캐스트 식 (캐스트식)과 달리 as 연산자는 예외를 throw 하지 않습니다.Unlike a cast expression (Cast expressions), the as operator never throws an exception. 대신, 표시 된 변환을 수행할 수 없는 경우 결과 값은 0 @no__t입니다.Instead, if the indicated conversion is not possible, the resulting value is null.

@No__t-0 형식의 작업에서 E은 식 이어야 하 고 T는 참조 형식 이거나 참조 형식으로 알려진 형식 매개 변수 이거나 nullable 형식 이어야 합니다.In an operation of the form E as T, E must be an expression and T must be a reference type, a type parameter known to be a reference type, or a nullable type. 또한 다음 중 하나 이상이 true 이거나 그렇지 않으면 컴파일 시간 오류가 발생 합니다.Furthermore, at least one of the following must be true, or otherwise a compile-time error occurs:

@No__t의 컴파일 시간 형식이-0 @no__t 되지 않은 경우-2 @no__t 작업은와 동일한 결과를 생성 합니다.If the compile-time type of E is not dynamic, the operation E as T produces the same result as

E is T ? (T)(E) : (T)null

단, E가 한 번만 계산됩니다.except that E is only evaluated once. 위의 확장에서 암시 하는 두 개의 동적 형식 검사와는 달리 컴파일러는 @no__t 최적화 하 여 최대 하나의 동적 형식 검사를 수행 하도록 예상할 수 있습니다.The compiler can be expected to optimize E as T to perform at most one dynamic type check as opposed to the two dynamic type checks implied by the expansion above.

@No__t-0의 컴파일 타임 형식이 dynamic 인 경우 캐스트 연산자와는 달리 as 연산자는 동적으로 바인딩되지 않습니다 (동적 바인딩).If the compile-time type of E is dynamic, unlike the cast operator the as operator is not dynamically bound (Dynamic binding). 따라서이 경우 확장은 다음과 같습니다.Therefore the expansion in this case is:

E is T ? (T)(object)(E) : (T)null

사용자 정의 변환과 같은 일부 변환은 as 연산자를 사용 하 여 사용할 수 없으며 대신 캐스트 식을 사용 하 여 수행 해야 합니다.Note that some conversions, such as user defined conversions, are not possible with the as operator and should instead be performed using cast expressions.

예제에서In the example

class X
{

    public string F(object o) {
        return o as string;        // OK, string is a reference type
    }

    public T G<T>(object o) where T: Attribute {
        return o as T;             // Ok, T has a class constraint
    }

    public U H<U>(object o) {
        return o as U;             // Error, U is unconstrained 
    }
}

G의 형식 매개 변수 @no__t은 클래스 제약 조건이 있기 때문에 참조 형식으로 알려져 있습니다.the type parameter T of G is known to be a reference type, because it has the class constraint. @No__t-1의 U 인 형식 매개 변수는 그렇지 않습니다. 따라서 H에서 as 연산자를 사용할 수 없습니다.The type parameter U of H is not however; hence the use of the as operator in H is disallowed.

논리 연산자Logical operators

@No__t-0, ^| 연산자를 논리 연산자 라고 합니다.The &, ^, and | operators are called the logical operators.

and_expression
    : equality_expression
    | and_expression '&' equality_expression
    ;

exclusive_or_expression
    : and_expression
    | exclusive_or_expression '^' and_expression
    ;

inclusive_or_expression
    : exclusive_or_expression
    | inclusive_or_expression '|' exclusive_or_expression
    ;

논리 연산자의 피연산자에 컴파일 타임 형식 dynamic이 있으면 식이 동적으로 바인딩됩니다 (동적 바인딩).If an operand of a logical operator has the compile-time type dynamic, then the expression is dynamically bound (Dynamic binding). 이 경우 식의 컴파일 시간 형식은 dynamic 이며 아래에 설명 된 해결 방법은 컴파일 시간 @no__t 형식이-1 인 피연산자의 런타임 형식을 사용 하 여 런타임에 수행 됩니다.In this case the compile-time type of the expression is dynamic, and the resolution described below will take place at run-time using the run-time type of those operands that have the compile-time type dynamic.

-1 @no__t 논리 연산자 중 하나인 경우 x op y 형식의 작업에 대해 오버 로드 확인 (이진 연산자 오버 로드 확인)이 적용 되어 특정 연산자 구현을 선택 합니다.For an operation of the form x op y, where op is one of the logical operators, overload resolution (Binary operator overload resolution) is applied to select a specific operator implementation. 피연산자는 선택한 연산자의 매개 변수 형식으로 변환 되 고 결과의 형식은 연산자의 반환 형식입니다.The operands are converted to the parameter types of the selected operator, and the type of the result is the return type of the operator.

미리 정의 된 논리 연산자에 대해서는 다음 섹션에서 설명 합니다.The predefined logical operators are described in the following sections.

정수 논리 연산자Integer logical operators

미리 정의 된 정수 논리 연산자는 다음과 같습니다.The predefined integer logical operators are:

int operator &(int x, int y);
uint operator &(uint x, uint y);
long operator &(long x, long y);
ulong operator &(ulong x, ulong y);

int operator |(int x, int y);
uint operator |(uint x, uint y);
long operator |(long x, long y);
ulong operator |(ulong x, ulong y);

int operator ^(int x, int y);
uint operator ^(uint x, uint y);
long operator ^(long x, long y);
ulong operator ^(ulong x, ulong y);

@No__t-0 연산자는 두 피연산자의 비트 논리 @no__t 1을 계산 하 고, | 연산자는 두 피연산자의 비트 논리적 @no__t 3을 계산 하며, ^ 연산자는 두 피연산자의 비트 논리적 배타적 @no__t을 계산 합니다.The & operator computes the bitwise logical AND of the two operands, the | operator computes the bitwise logical OR of the two operands, and the ^ operator computes the bitwise logical exclusive OR of the two operands. 이러한 작업에서 오버플로를 수행할 수 없습니다.No overflows are possible from these operations.

열거형 논리 연산자Enumeration logical operators

모든 열거형 형식 E은 다음과 같이 미리 정의 된 논리 연산자를 암시적으로 제공 합니다.Every enumeration type E implicitly provides the following predefined logical operators:

E operator &(E x, E y);
E operator |(E x, E y);
E operator ^(E x, E y);

@No__t-@no__t 0을 평가한 결과-1과 y는 기본 형식이 U이 고, op는 논리 연산자 중 하나 E, @no__t을 평가 하는 것과 정확히 동일 합니다.The result of evaluating x op y, where x and y are expressions of an enumeration type E with an underlying type U, and op is one of the logical operators, is exactly the same as evaluating (E)((U)x op (U)y). 즉, 열거형 형식 논리 연산자는 두 피연산자의 기본 형식에 대 한 논리적 연산을 수행 합니다.In other words, the enumeration type logical operators simply perform the logical operation on the underlying type of the two operands.

부울 논리 연산자Boolean logical operators

미리 정의 된 부울 논리 연산자는 다음과 같습니다.The predefined boolean logical operators are:

bool operator &(bool x, bool y);
bool operator |(bool x, bool y);
bool operator ^(bool x, bool y);

xy가 모두 true인 경우 x & y의 결과는 true입니다.The result of x & y is true if both x and y are true. 그렇지 않으면 결과는 false입니다.Otherwise, the result is false.

@No__t-0은 x 또는 ytrue 인 경우 true입니다.The result of x | y is true if either x or y is true. 그렇지 않으면 결과는 false입니다.Otherwise, the result is false.

@No__t-@no__t 0은 xtrue이 고 yfalse 이거나 yfalse 인 경우-1입니다.The result of x ^ y is true if x is true and y is false, or x is false and y is true. 그렇지 않으면 결과는 false입니다.Otherwise, the result is false. 피연산자의 형식이 bool 인 경우 ^ 연산자는 != 연산자와 동일한 결과를 계산 합니다.When the operands are of type bool, the ^ operator computes the same result as the != operator.

Nullable 부울 논리 연산자Nullable boolean logical operators

Nullable 부울 형식 bool?true, falsenull의 세 가지 값을 나타낼 수 있으며, SQL의 부울 식에 사용 되는 세 값 형식과 개념적으로 유사 합니다.The nullable boolean type bool? can represent three values, true, false, and null, and is conceptually similar to the three-valued type used for boolean expressions in SQL. @No__t-2 피연산자에 대 한 &| 연산자로 생성 된 결과가 SQL의 3 값 논리와 일치 하는지 확인 하려면 다음과 같은 미리 정의 된 연산자를 제공 합니다.To ensure that the results produced by the & and | operators for bool? operands are consistent with SQL's three-valued logic, the following predefined operators are provided:

bool? operator &(bool? x, bool? y);
bool? operator |(bool? x, bool? y);

다음 표에서는 값의 모든 조합에 대해 이러한 연산자에 의해 생성 되는 결과를 나열 true, falsenull입니다.The following table lists the results produced by these operators for all combinations of the values true, false, and null.

x y x & y x | y
true true true true
true false false true
true null null true
false true false true
false false false false
false null false null
null true null true
null false false null
null null null null

조건부 논리 연산자Conditional logical operators

@No__t-0 및 || 연산자를 조건부 논리 연산자 라고 합니다.The && and || operators are called the conditional logical operators. 이러한 논리 연산자를 "단락" 논리 연산자 라고도 합니다.They are also called the "short-circuiting" logical operators.

conditional_and_expression
    : inclusive_or_expression
    | conditional_and_expression '&&' inclusive_or_expression
    ;

conditional_or_expression
    : conditional_and_expression
    | conditional_or_expression '||' conditional_and_expression
    ;

@No__t-0 및 || 연산자는 &| 연산자의 조건부 버전입니다.The && and || operators are conditional versions of the & and | operators:

  • @No__t-0은-1 x이 @no__t 되지 않은 경우에만 x & y @no__t 작업에 해당 합니다.The operation x && y corresponds to the operation x & y, except that y is evaluated only if x is not false.
  • @No__t-0은-1 x이 @no__t 되지 않은 경우에만 x | y @no__t 작업에 해당 합니다.The operation x || y corresponds to the operation x | y, except that y is evaluated only if x is not true.

조건부 논리 연산자의 피연산자에 컴파일 타임 형식 dynamic이 있으면 식이 동적으로 바인딩됩니다 (동적 바인딩).If an operand of a conditional logical operator has the compile-time type dynamic, then the expression is dynamically bound (Dynamic binding). 이 경우 식의 컴파일 시간 형식은 dynamic 이며 아래에 설명 된 해결 방법은 컴파일 시간 @no__t 형식이-1 인 피연산자의 런타임 형식을 사용 하 여 런타임에 수행 됩니다.In this case the compile-time type of the expression is dynamic, and the resolution described below will take place at run-time using the run-time type of those operands that have the compile-time type dynamic.

@No__t-0 또는 x || y @no__t @no__t 작업이 작성 된 것 처럼 오버 로드 확인 (이항 연산자 오버 로드 확인)을 적용 하 여 처리 됩니다.An operation of the form x && y or x || y is processed by applying overload resolution (Binary operator overload resolution) as if the operation was written x & y or x | y. 다음Then,

조건부 논리 연산자를 직접 오버 로드할 수는 없습니다.It is not possible to directly overload the conditional logical operators. 그러나 조건부 논리 연산자는 일반 논리 연산자를 기준으로 계산 되기 때문에 일반적인 논리 연산자의 오버 로드는 조건부 논리 연산자의 오버 로드로 간주 되는 특정 제한 사항이 있습니다.However, because the conditional logical operators are evaluated in terms of the regular logical operators, overloads of the regular logical operators are, with certain restrictions, also considered overloads of the conditional logical operators. 사용자 정의 조건부 논리 연산자에 대해서는이에 대해 자세히 설명 합니다.This is described further in User-defined conditional logical operators.

부울 조건부 논리 연산자Boolean conditional logical operators

@No__t-0 또는 ||의 피연산자가 bool 형식 이거나 피연산자가 적용 가능한 operator & 또는 operator |를 정의 하지 않는 형식인 경우, bool로의 암시적 변환을 정의 하는 경우 작업은 다음과 같이 처리 됩니다. :When the operands of && or || are of type bool, or when the operands are of types that do not define an applicable operator & or operator |, but do define implicit conversions to bool, the operation is processed as follows:

  • 작업 x && yx ? y : false로 계산 됩니다.The operation x && y is evaluated as x ? y : false. 즉, x이 먼저 평가 되 고 bool 형식으로 변환 됩니다.In other words, x is first evaluated and converted to type bool. @No__t-0이-1 @no__t y가 평가 되 고 bool 형식으로 변환 되며,이는 작업의 결과가 됩니다.Then, if x is true, y is evaluated and converted to type bool, and this becomes the result of the operation. 그렇지 않으면 작업 결과가-0 @no__t 됩니다.Otherwise, the result of the operation is false.
  • 작업 x || yx ? true : y로 계산 됩니다.The operation x || y is evaluated as x ? true : y. 즉, x이 먼저 평가 되 고 bool 형식으로 변환 됩니다.In other words, x is first evaluated and converted to type bool. @No__t-0이-1 @no__t 이면 작업의 결과는-2 @no__t 됩니다.Then, if x is true, the result of the operation is true. 그렇지 않으면 y이 평가 되 고 bool 형식으로 변환 되며,이는 작업의 결과가 됩니다.Otherwise, y is evaluated and converted to type bool, and this becomes the result of the operation.

사용자 지정 조건부 논리 연산자User-defined conditional logical operators

@No__t-0 또는 ||의 피연산자가 해당 하는 사용자 정의 @no__t 2 또는 operator |을 선언 하는 형식인 경우 다음 두 가지 모두 true 여야 합니다. 여기서 T는 선택한 연산자가 선언 된 형식입니다.When the operands of && or || are of types that declare an applicable user-defined operator & or operator |, both of the following must be true, where T is the type in which the selected operator is declared:

  • 선택한 연산자의 각 매개 변수 형식 및 반환 형식은-0 @no__t 이어야 합니다.The return type and the type of each parameter of the selected operator must be T. 즉, 연산자는 논리적 AND 또는 T 형식의 두 피연산자의 논리적 OR을 계산 해야 하며 T 형식의 결과를 반환 해야 합니다.In other words, the operator must compute the logical AND or the logical OR of two operands of type T, and must return a result of type T.
  • Toperator trueoperator false의 선언을 포함 해야 합니다.T must contain declarations of operator true and operator false.

이러한 요구 사항 중 하나가 충족 되지 않으면 바인딩 시간 오류가 발생 합니다.A binding-time error occurs if either of these requirements is not satisfied. 그렇지 않으면 사용자 정의 operator true 또는 operator false을 선택한 사용자 정의 연산자와 결합 하 여 && 또는 || 작업이 평가 됩니다.Otherwise, the && or || operation is evaluated by combining the user-defined operator true or operator false with the selected user-defined operator:

  • 작업 x && yT.false(x) ? x : T.&(x, y)로 계산 됩니다. 여기서 T.false(x)T에 선언 된 operator false을 호출 하 고 T.&(x, y)는 선택한 operator &의 호출입니다.The operation x && y is evaluated as T.false(x) ? x : T.&(x, y), where T.false(x) is an invocation of the operator false declared in T, and T.&(x, y) is an invocation of the selected operator &. 즉, x이 먼저 평가 되 고 결과에 대 한 operator false이 호출 되어 x가 명확 하 게 false 인지 확인 합니다.In other words, x is first evaluated and operator false is invoked on the result to determine if x is definitely false. 그런 다음 x이 명확 하 게 false 이면 연산 결과는 x에 대해 이전에 계산 된 값입니다.Then, if x is definitely false, the result of the operation is the value previously computed for x. 그렇지 않으면 y이 계산 되 고, 선택한 operator &x에 대해 이전에 계산 된 값에 대해 호출 되 고, y에 대해 계산 된 값을 호출 하 여 작업의 결과를 생성 합니다.Otherwise, y is evaluated, and the selected operator & is invoked on the value previously computed for x and the value computed for y to produce the result of the operation.
  • 작업 x || yT.true(x) ? x : T.|(x, y)로 계산 됩니다. 여기서 T.true(x)T에 선언 된 operator true을 호출 하 고 T.|(x,y)는 선택한 operator|의 호출입니다.The operation x || y is evaluated as T.true(x) ? x : T.|(x, y), where T.true(x) is an invocation of the operator true declared in T, and T.|(x,y) is an invocation of the selected operator|. 즉, x이 먼저 평가 되 고 결과에 대 한 operator true이 호출 되어 x가 확실히 true 인지 확인 합니다.In other words, x is first evaluated and operator true is invoked on the result to determine if x is definitely true. 그런 다음 x이 명확 하 게 true 이면 연산 결과는 x에 대해 이전에 계산 된 값입니다.Then, if x is definitely true, the result of the operation is the value previously computed for x. 그렇지 않으면 y이 계산 되 고, 선택한 operator |x에 대해 이전에 계산 된 값에 대해 호출 되 고, y에 대해 계산 된 값을 호출 하 여 작업의 결과를 생성 합니다.Otherwise, y is evaluated, and the selected operator | is invoked on the value previously computed for x and the value computed for y to produce the result of the operation.

이러한 작업 중 하나에서 x으로 지정 된 식은 한 번만 계산 되며 y로 지정 된 식은 정확히 한 번만 계산 되거나 계산 되지 않습니다.In either of these operations, the expression given by x is only evaluated once, and the expression given by y is either not evaluated or evaluated exactly once.

@No__t-0 및 operator false을 구현 하는 형식의 예는 데이터베이스 부울 형식을 참조 하세요.For an example of a type that implements operator true and operator false, see Database boolean type.

Null 병합 연산자The null coalescing operator

@No__t-0 연산자를 null 병합 연산자 라고 합니다.The ?? operator is called the null coalescing operator.

null_coalescing_expression
    : conditional_or_expression
    | conditional_or_expression '??' null_coalescing_expression
    ;

@No__t-@no__t 0 형식의 null 결합 식에는 nullable 형식 또는 참조 형식 이어야 합니다.A null coalescing expression of the form a ?? b requires a to be of a nullable type or reference type. @No__t-0이 null이 아닌 경우 a ?? b의 결과는 a입니다. 그렇지 않으면 결과는-3 @no__t 됩니다.If a is non-null, the result of a ?? b is a; otherwise, the result is b. -1 @no__t가 null 인 경우에만 작업에서 b이 반환 됩니다.The operation evaluates b only if a is null.

Null 병합 연산자는 오른쪽 결합성이 있습니다. 즉, 작업은 오른쪽에서 왼쪽으로 그룹화 됩니다.The null coalescing operator is right-associative, meaning that operations are grouped from right to left. 예를 들어 a ?? b ?? c 형식의 식은 a ?? (b ?? c)로 계산 됩니다.For example, an expression of the form a ?? b ?? c is evaluated as a ?? (b ?? c). 일반적으로 E1 ?? E2 ?? ... ?? En 형식의 식은 null이 아닌 피연산자 중 첫 번째를 반환 하거나, 모든 피연산자가 null 인 경우 null을 반환 합니다.In general terms, an expression of the form E1 ?? E2 ?? ... ?? En returns the first of the operands that is non-null, or null if all operands are null.

식의 형식 a ?? b은 피연산자에서 사용할 수 있는 암시적 변환에 따라 다릅니다.The type of the expression a ?? b depends on which implicit conversions are available on the operands. 기본 설정 순서에 따라-0 @no__t의 형식은 A0, A 또는 B입니다. 여기서 A는 @no__t 형식입니다. 여기서 B은 @no__t 형식입니다. (b에 형식이 있는 경우)은 b의 유형입니다. 0은 2가 nullable @no__t 형식이 면-11 @no__t의 기본 형식이 며, 그렇지 않으면-13입니다.In order of preference, the type of a ?? b is A0, A, or B, where A is the type of a (provided that a has a type), B is the type of b (provided that b has a type), and A0 is the underlying type of A if A is a nullable type, or A otherwise. 특히 a ?? b은 다음과 같이 처리 됩니다.Specifically, a ?? b is processed as follows:

  • @No__t-0이 있고 nullable 형식 또는 참조 형식이 아닌 경우 컴파일 타임 오류가 발생 합니다.If A exists and is not a nullable type or a reference type, a compile-time error occurs.
  • @No__t-0이 동적 식인 경우 결과 형식은-1 @no__t 됩니다.If b is a dynamic expression, the result type is dynamic. 런타임에 a이 먼저 계산 됩니다.At run-time, a is first evaluated. @No__t-0이 null이 아니면-1 @no__t 동적으로 변환 되 고 결과가 됩니다.If a is not null, a is converted to dynamic, and this becomes the result. 그렇지 않으면 b이 계산 되며이는 결과가 됩니다.Otherwise, b is evaluated, and this becomes the result.
  • 그렇지 않고 A이 있고 nullable 형식이 며 b에서 A0로의 암시적 변환이 있는 경우 결과 형식은-3 @no__t입니다.Otherwise, if A exists and is a nullable type and an implicit conversion exists from b to A0, the result type is A0. 런타임에 a이 먼저 계산 됩니다.At run-time, a is first evaluated. @No__t-0이 null이 아니면-1 @no__t A0 형식으로 래핑 해제 되 고 결과가 됩니다.If a is not null, a is unwrapped to type A0, and this becomes the result. 그렇지 않으면 b이 계산 되어 A0 형식으로 변환 되며이는 결과가 됩니다.Otherwise, b is evaluated and converted to type A0, and this becomes the result.
  • 그렇지 않고 A이 있고 b에서 A로의 암시적 변환이 있는 경우 결과 형식은-3 @no__t입니다.Otherwise, if A exists and an implicit conversion exists from b to A, the result type is A. 런타임에 a이 먼저 계산 됩니다.At run-time, a is first evaluated. @No__t-0이 null이 아니면-1 @no__t 결과가 됩니다.If a is not null, a becomes the result. 그렇지 않으면 b이 계산 되어 A 형식으로 변환 되며이는 결과가 됩니다.Otherwise, b is evaluated and converted to type A, and this becomes the result.
  • @No__t-0에 B 형식이 있고 a에서 B으로의 암시적 변환이 있는 경우 결과 형식은 B입니다.Otherwise, if b has a type B and an implicit conversion exists from a to B, the result type is B. 런타임에 a이 먼저 계산 됩니다.At run-time, a is first evaluated. @No__t-0이 null이 아니면-1 @no__t A0 형식으로 래핑 해제 되 고 (A이 존재 하 고 null을 허용 하는 경우) B 형식으로 변환 되며이는 결과가 됩니다.If a is not null, a is unwrapped to type A0 (if A exists and is nullable) and converted to type B, and this becomes the result. 그렇지 않으면 b이 평가 되 고 결과가 됩니다.Otherwise, b is evaluated and becomes the result.
  • 그렇지 않으면 ab이 호환 되지 않으며 컴파일 시간 오류가 발생 합니다.Otherwise, a and b are incompatible, and a compile-time error occurs.

조건 연산자Conditional operator

@No__t-0 연산자를 조건 연산자 라고 합니다.The ?: operator is called the conditional operator. 때로는 삼항 연산자 라고도 합니다.It is at times also called the ternary operator.

conditional_expression
    : null_coalescing_expression
    | null_coalescing_expression '?' expression ':' expression
    ;

@No__t-0 형식의 조건 식이 먼저-1 @no__t 조건을 평가 합니다.A conditional expression of the form b ? x : y first evaluates the condition b. @No__t-0이-1 @no__t x가 평가 되 고 작업 결과가 됩니다.Then, if b is true, x is evaluated and becomes the result of the operation. 그렇지 않으면 y이 평가 되 고 작업 결과가 됩니다.Otherwise, y is evaluated and becomes the result of the operation. 조건식은 xy을 모두 계산 하지 않습니다.A conditional expression never evaluates both x and y.

조건 연산자는 오른쪽 결합성이 있습니다. 즉, 작업은 오른쪽에서 왼쪽으로 그룹화 됩니다.The conditional operator is right-associative, meaning that operations are grouped from right to left. 예를 들어 a ? b : c ? d : e 형식의 식은 a ? b : (c ? d : e)로 계산 됩니다.For example, an expression of the form a ? b : c ? d : e is evaluated as a ? b : (c ? d : e).

@No__t-0 연산자의 첫 번째 피연산자는 bool로 암시적으로 변환할 수 있는 식 이거나 operator true를 구현 하는 형식의 식 이어야 합니다.The first operand of the ?: operator must be an expression that can be implicitly converted to bool, or an expression of a type that implements operator true. 이러한 요구 사항 중 하나라도 충족 되지 않으면 컴파일 시간 오류가 발생 합니다.If neither of these requirements is satisfied, a compile-time error occurs.

@No__t-2 연산자의 두 번째 및 세 번째 피연산자 xy은 조건 식의 형식을 제어 합니다.The second and third operands, x and y, of the ?: operator control the type of the conditional expression.

  • @No__t-0의 형식이 X이 고 y의 형식이 Y 인 경우If x has type X and y has type Y then
    • 암시적 변환 (암시적 변환)이 X에서 Y로만 존재 하지만 @no__t-@no__t 3에서-4로 변환 되지 않은 경우 Y는 조건식의 유형입니다.If an implicit conversion (Implicit conversions) exists from X to Y, but not from Y to X, then Y is the type of the conditional expression.
    • 암시적 변환 (암시적 변환)이 Y에서 X로만 존재 하지만 @no__t-@no__t 3에서-4로 변환 되지 않은 경우 X는 조건식의 유형입니다.If an implicit conversion (Implicit conversions) exists from Y to X, but not from X to Y, then X is the type of the conditional expression.
    • 그렇지 않으면 식 형식을 확인할 수 없고 컴파일 타임 오류가 발생 합니다.Otherwise, no expression type can be determined, and a compile-time error occurs.
  • @No__t-0 및 y 중 하나만 형식이 있고의 xy 모두 해당 형식으로 암시적으로 변환할 수 있는 경우이는 조건식의 형식입니다.If only one of x and y has a type, and both x and y, of are implicitly convertible to that type, then that is the type of the conditional expression.
  • 그렇지 않으면 식 형식을 확인할 수 없고 컴파일 타임 오류가 발생 합니다.Otherwise, no expression type can be determined, and a compile-time error occurs.

@No__t-0 형식의 조건 식에 대 한 런타임 처리는 다음 단계로 구성 됩니다.The run-time processing of a conditional expression of the form b ? x : y consists of the following steps:

  • 먼저 b이 평가 되 고 bbool 값이 결정 됩니다.First, b is evaluated, and the bool value of b is determined:
    • @No__t의 형식에서-1 @no__t로의 암시적 변환이 있는 경우이 암시적 변환은 bool 값을 생성 하기 위해 수행 됩니다.If an implicit conversion from the type of b to bool exists, then this implicit conversion is performed to produce a bool value.
    • 그렇지 않으면-1 @no__t 형식으로 정의 된 @no__t 0이 호출 되어 bool 값이 생성 됩니다.Otherwise, the operator true defined by the type of b is invoked to produce a bool value.
  • @No__t 위의 단계에서 생성 된 @no__t 값이-1 이면 x가 평가 되 고 조건식의 형식으로 변환 되며이는 조건식의 결과가 됩니다.If the bool value produced by the step above is true, then x is evaluated and converted to the type of the conditional expression, and this becomes the result of the conditional expression.
  • 그렇지 않으면-0 @no__t 평가 되 고 조건식의 형식으로 변환 되며이는 조건식의 결과가 됩니다.Otherwise, y is evaluated and converted to the type of the conditional expression, and this becomes the result of the conditional expression.

익명 함수 식Anonymous function expressions

익명 함수 는 "인라인" 메서드 정의를 나타내는 식입니다.An anonymous function is an expression that represents an "in-line" method definition. 익명 함수는 및의 자체에 값 또는 형식이 없지만 호환 되는 대리자 또는 식 트리 형식으로 변환할 수 있습니다.An anonymous function does not have a value or type in and of itself, but is convertible to a compatible delegate or expression tree type. 익명 함수 변환의 평가는 변환의 대상 유형에 따라 달라 집니다. 대리자 형식인 경우 변환은 익명 함수가 정의 하는 메서드를 참조 하는 대리자 값으로 평가 됩니다.The evaluation of an anonymous function conversion depends on the target type of the conversion: If it is a delegate type, the conversion evaluates to a delegate value referencing the method which the anonymous function defines. 식 트리 형식인 경우 변환은 메서드 구조를 개체 구조체로 나타내는 식 트리로 평가 됩니다.If it is an expression tree type, the conversion evaluates to an expression tree which represents the structure of the method as an object structure.

기록을 위해 익명 함수의 두 가지 구문, 즉 lambda_expressions와 anonymous_method_expressions가 있습니다.For historical reasons there are two syntactic flavors of anonymous functions, namely lambda_expressions and anonymous_method_expressions. 거의 모든 목적을 위해 lambda_expressions는 이전 버전과의 호환성을 위해 언어로 유지 되는 anonymous_method_expressions 보다 간결 하 고 표현 됩니다.For almost all purposes, lambda_expressions are more concise and expressive than anonymous_method_expressions, which remain in the language for backwards compatibility.

lambda_expression
    : anonymous_function_signature '=>' anonymous_function_body
    ;

anonymous_method_expression
    : 'delegate' explicit_anonymous_function_signature? block
    ;

anonymous_function_signature
    : explicit_anonymous_function_signature
    | implicit_anonymous_function_signature
    ;

explicit_anonymous_function_signature
    : '(' explicit_anonymous_function_parameter_list? ')'
    ;

explicit_anonymous_function_parameter_list
    : explicit_anonymous_function_parameter (',' explicit_anonymous_function_parameter)*
    ;

explicit_anonymous_function_parameter
    : anonymous_function_parameter_modifier? type identifier
    ;

anonymous_function_parameter_modifier
    : 'ref'
    | 'out'
    ;

implicit_anonymous_function_signature
    : '(' implicit_anonymous_function_parameter_list? ')'
    | implicit_anonymous_function_parameter
    ;

implicit_anonymous_function_parameter_list
    : implicit_anonymous_function_parameter (',' implicit_anonymous_function_parameter)*
    ;

implicit_anonymous_function_parameter
    : identifier
    ;

anonymous_function_body
    : expression
    | block
    ;

@No__t-0 연산자는 할당 (=)과 우선 순위가 같으며 오른쪽 결합성이 있습니다.The => operator has the same precedence as assignment (=) and is right-associative.

@No__t-0 한정자를 사용 하는 익명 함수는 비동기 함수 이며 반복기에 설명 된 규칙을 따릅니다.An anonymous function with the async modifier is an async function and follows the rules described in Iterators.

Lambda_expression 형식의 익명 함수 매개 변수는 명시적 또는 암시적으로 형식화 될 수 있습니다.The parameters of an anonymous function in the form of a lambda_expression can be explicitly or implicitly typed. 명시적으로 형식화 된 매개 변수 목록에서 각 매개 변수의 형식은 명시적으로 지정 됩니다.In an explicitly typed parameter list, the type of each parameter is explicitly stated. 암시적으로 형식화 된 매개 변수 목록에서 매개 변수의 형식은 익명 함수가 발생 하는 컨텍스트에서 유추 됩니다. 특히 익명 함수가 호환 되는 대리자 형식 또는 식 트리 형식으로 변환 되는 경우이 형식은를 제공 합니다. 매개 변수 형식 (익명 함수 변환)입니다.In an implicitly typed parameter list, the types of the parameters are inferred from the context in which the anonymous function occurs—specifically, when the anonymous function is converted to a compatible delegate type or expression tree type, that type provides the parameter types (Anonymous function conversions).

암시적으로 형식화 된 단일 매개 변수를 사용 하는 익명 함수에서 괄호는 매개 변수 목록에서 생략 될 수 있습니다.In an anonymous function with a single, implicitly typed parameter, the parentheses may be omitted from the parameter list. 즉, 폼의 익명 함수In other words, an anonymous function of the form

( param ) => expr

축약 가능can be abbreviated to

param => expr

Anonymous_method_expression 형식의 익명 함수에 대 한 매개 변수 목록은 선택 사항입니다.The parameter list of an anonymous function in the form of an anonymous_method_expression is optional. 지정 된 경우 매개 변수를 명시적으로 형식화 해야 합니다.If given, the parameters must be explicitly typed. 그렇지 않은 경우 익명 함수는 out 매개 변수를 포함 하지 않는 매개 변수 목록을 사용 하 여 대리자로 변환할 수 있습니다.If not, the anonymous function is convertible to a delegate with any parameter list not containing out parameters.

익명 함수는 접근할 수 없는 문 내에서 발생 하지 않는 한 익명 함수의 블록 본문에 연결할 수 있습니다 (끝점 및 연결 가능성).A block body of an anonymous function is reachable (End points and reachability) unless the anonymous function occurs inside an unreachable statement.

익명 함수의 몇 가지 예는 다음과 같습니다.Some examples of anonymous functions follow below:

x => x + 1                              // Implicitly typed, expression body
x => { return x + 1; }                  // Implicitly typed, statement body
(int x) => x + 1                        // Explicitly typed, expression body
(int x) => { return x + 1; }            // Explicitly typed, statement body
(x, y) => x * y                         // Multiple parameters
() => Console.WriteLine()               // No parameters
async (t1,t2) => await t1 + await t2    // Async
delegate (int x) { return x + 1; }      // Anonymous method expression
delegate { return 1 + 1; }              // Parameter list omitted

Lambda_expressions 및 anonymous_method_expressions의 동작은 다음 사항을 제외 하 고 동일 합니다.The behavior of lambda_expressions and anonymous_method_expressions is the same except for the following points:

  • anonymous_method_expressions를 지정 하면 매개 변수 목록을 완전히 생략할 수 있으며, convertibility을 생성 하 여 값 매개 변수 목록의 형식을 위임 합니다.anonymous_method_expressions permit the parameter list to be omitted entirely, yielding convertibility to delegate types of any list of value parameters.
  • lambda_expressions에서는 매개 변수 형식을 생략 하 고 유추 하도록 허용 하는 반면, anonymous_method_expressions에서는 매개 변수 형식을 명시적으로 지정 해야 합니다.lambda_expressions permit parameter types to be omitted and inferred whereas anonymous_method_expressions require parameter types to be explicitly stated.
  • Lambda_expression 의 본문은 식 또는 문 블록이 될 수 있지만 anonymous_method_expression 본문은 문 블록 이어야 합니다.The body of a lambda_expression can be an expression or a statement block whereas the body of an anonymous_method_expression must be a statement block.
  • Lambda_expressions만 호환 식 트리 형식 (식 트리 형식)으로 변환 합니다.Only lambda_expressions have conversions to compatible expression tree types (Expression tree types).

익명 함수 서명Anonymous function signatures

익명 함수의 선택적 anonymous_function_signature 는 익명 함수에 대 한 형식 매개 변수의 형식 및 이름을 정의 합니다.The optional anonymous_function_signature of an anonymous function defines the names and optionally the types of the formal parameters for the anonymous function. 익명 함수의 매개 변수 범위는 anonymous_function_body입니다.The scope of the parameters of the anonymous function is the anonymous_function_body. (범위) 매개 변수 목록 (지정 된 경우)과 함께 무명 메서드 본문은 선언 공간 (선언)을 구성 합니다.(Scopes) Together with the parameter list (if given) the anonymous-method-body constitutes a declaration space (Declarations). 따라서 익명 함수의 매개 변수 이름이 범위에 anonymous_method_expression 또는 lambda_expression를 포함 하는 지역 변수, 로컬 상수 또는 매개 변수의 이름과 일치 하는 컴파일 시간 오류가 발생 합니다.It is thus a compile-time error for the name of a parameter of the anonymous function to match the name of a local variable, local constant or parameter whose scope includes the anonymous_method_expression or lambda_expression.

익명 함수에 explicit_anonymous_function_signature이 있는 경우 호환 되는 대리자 형식 및 식 트리 형식의 집합은 동일한 순서로 매개 변수 형식 및 한정자가 있는 것으로 제한 됩니다.If an anonymous function has an explicit_anonymous_function_signature, then the set of compatible delegate types and expression tree types is restricted to those that have the same parameter types and modifiers in the same order. 메서드 그룹 변환 (메서드 그룹 변환)과 달리, 차감-익명 함수 매개 변수 형식의 분산은 지원 되지 않습니다.In contrast to method group conversions (Method group conversions), contra-variance of anonymous function parameter types is not supported. 익명 함수에 anonymous_function_signature없는 경우 호환 되는 대리자 형식 및 식 트리 형식의 집합은 out 매개 변수가 없는 매개 변수로 제한 됩니다.If an anonymous function does not have an anonymous_function_signature, then the set of compatible delegate types and expression tree types is restricted to those that have no out parameters.

Anonymous_function_signature 는 특성 또는 매개 변수 배열을 포함할 수 없습니다.Note that an anonymous_function_signature cannot include attributes or a parameter array. 그럼에도 불구 하 고 anonymous_function_signature 는 매개 변수 목록이 매개 변수 배열을 포함 하는 대리자 형식과 호환 될 수 있습니다.Nevertheless, an anonymous_function_signature may be compatible with a delegate type whose parameter list contains a parameter array.

또한 식 트리 형식으로의 변환은 호환 되는 경우에도 컴파일 시간 (식 트리 형식)에서 실패할 수 있습니다.Note also that conversion to an expression tree type, even if compatible, may still fail at compile-time (Expression tree types).

익명 함수 본문Anonymous function bodies

익명 함수의 본문 ( 또는 블록)에는 다음 규칙이 적용 됩니다.The body (expression or block) of an anonymous function is subject to the following rules:

  • 익명 함수에 시그니처가 포함 되어 있으면 서명에 지정 된 매개 변수를 본문에서 사용할 수 있습니다.If the anonymous function includes a signature, the parameters specified in the signature are available in the body. 익명 함수에 시그니처가 없으면 매개 변수 (익명 함수 변환)를 포함 하는 대리자 형식 또는 식 형식으로 변환할 수 있지만 본문에서 매개 변수에 액세스할 수는 없습니다.If the anonymous function has no signature it can be converted to a delegate type or expression type having parameters (Anonymous function conversions), but the parameters cannot be accessed in the body.
  • 가장 가까운 바깥쪽 익명 함수의 서명 (있는 경우)에 지정 된 ref 또는 out 매개 변수를 제외 하 고는 본문이 ref 또는 out 매개 변수에 액세스 하는 컴파일 시간 오류입니다.Except for ref or out parameters specified in the signature (if any) of the nearest enclosing anonymous function, it is a compile-time error for the body to access a ref or out parameter.
  • @No__t의 형식이 구조체 형식이 면 본문이 this에 액세스 하는 컴파일 시간 오류가 발생 합니다.When the type of this is a struct type, it is a compile-time error for the body to access this. 이는 액세스가 명시적 (this.x) 또는 암시적 (x가 구조체의 인스턴스 멤버인 x) 인지 여부에 해당 합니다.This is true whether the access is explicit (as in this.x) or implicit (as in x where x is an instance member of the struct). 이 규칙은 이러한 액세스를 금지 하기만 하 고 멤버 조회 결과가 구조체의 멤버 인지 여부에 영향을 주지 않습니다.This rule simply prohibits such access and does not affect whether member lookup results in a member of the struct.
  • 본문은 익명 함수의 외부 변수 (외부 변수)에 액세스할 수 있습니다.The body has access to the outer variables (Outer variables) of the anonymous function. 외부 변수에 대 한 액세스는 lambda_expression 또는 anonymous_method_expression 가 계산 될 때 활성화 되는 변수의 인스턴스를 참조 합니다 (익명 함수 식의 계산).Access of an outer variable will reference the instance of the variable that is active at the time the lambda_expression or anonymous_method_expression is evaluated (Evaluation of anonymous function expressions).
  • 본문이 본문 외부에 있거나 포함 된 익명 함수의 본문에 있는 goto 문, break 문 또는 continue 문을 포함 하는 컴파일 시간 오류입니다.It is a compile-time error for the body to contain a goto statement, break statement, or continue statement whose target is outside the body or within the body of a contained anonymous function.
  • 본문의 return 문은 바깥쪽 함수 멤버가 아니라 가장 가까운 바깥쪽 무명 함수를 호출 하 여 제어를 반환 합니다.A return statement in the body returns control from an invocation of the nearest enclosing anonymous function, not from the enclosing function member. @No__t-0 문에 지정 된 식은 가장 가까운 바깥쪽 lambda_expression 또는 anonymous_method_expression 가 변환 되는 대리자 형식 또는 식 트리 형식의 반환 형식으로 암시적으로 변환할 수 있어야 합니다 ( 익명 함수 변환).An expression specified in a return statement must be implicitly convertible to the return type of the delegate type or expression tree type to which the nearest enclosing lambda_expression or anonymous_method_expression is converted (Anonymous function conversions).

Lambda_expression 또는 anonymous_method_expression의 평가 및 호출을 통해서가 아닌 익명 함수의 블록을 실행 하는 방법이 있는지 여부는 명시적으로 지정 되지 않습니다.It is explicitly unspecified whether there is any way to execute the block of an anonymous function other than through evaluation and invocation of the lambda_expression or anonymous_method_expression. 특히 컴파일러는 하나 이상의 명명 된 메서드 또는 형식을 synthesizing 하 여 익명 함수를 구현 하도록 선택할 수 있습니다.In particular, the compiler may choose to implement an anonymous function by synthesizing one or more named methods or types. 이러한 합성 요소의 이름은 컴파일러 사용을 위해 예약 된 형식 이어야 합니다.The names of any such synthesized elements must be of a form reserved for compiler use.

오버 로드 확인 및 익명 함수Overload resolution and anonymous functions

인수 목록의 익명 함수는 형식 유추 및 오버 로드 확인에 참여 합니다.Anonymous functions in an argument list participate in type inference and overload resolution. 정확한 규칙은 형식 유추오버 로드 확인 을 참조 하세요.Please refer to Type inference and Overload resolution for the exact rules.

다음 예제에서는 오버 로드 확인에 대 한 익명 함수의 효과를 보여 줍니다.The following example illustrates the effect of anonymous functions on overload resolution.

class ItemList<T>: List<T>
{
    public int Sum(Func<T,int> selector) {
        int sum = 0;
        foreach (T item in this) sum += selector(item);
        return sum;
    }

    public double Sum(Func<T,double> selector) {
        double sum = 0;
        foreach (T item in this) sum += selector(item);
        return sum;
    }
}

@No__t-0 클래스에는 두 개의 Sum 메서드가 있습니다.The ItemList<T> class has two Sum methods. 는 모두 목록 항목에서 합계를 계산 하기 위해 값을 추출 하는 selector 인수를 사용 합니다.Each takes a selector argument, which extracts the value to sum over from a list item. 추출 된 값은 @no__t 0 이거나 double 일 수 있으며 결과 합계는 int 또는 double 일 수 있습니다.The extracted value can be either an int or a double and the resulting sum is likewise either an int or a double.

예를 들어 Sum 메서드를 사용 하 여 세부 정보 줄 목록에서 특정 순서로 합계를 계산할 수 있습니다.The Sum methods could for example be used to compute sums from a list of detail lines in an order.

class Detail
{
    public int UnitCount;
    public double UnitPrice;
    ...
}

void ComputeSums() {
    ItemList<Detail> orderDetails = GetOrderDetails(...);
    int totalUnits = orderDetails.Sum(d => d.UnitCount);
    double orderTotal = orderDetails.Sum(d => d.UnitPrice * d.UnitCount);
    ...
}

@No__t-0의 첫 번째 호출에서는 익명 함수 d => d. UnitCount가 @no__t 3과 Func<Detail,double> 모두와 호환 되기 때문에 Sum 메서드를 모두 사용할 수 있습니다.In the first invocation of orderDetails.Sum, both Sum methods are applicable because the anonymous function d => d. UnitCount is compatible with both Func<Detail,int> and Func<Detail,double>. 그러나 Func<Detail,int>로 변환 하는 것이 Func<Detail,double>로 변환 하는 것 보다 더 우수 하기 때문에 오버 로드 확인은 첫 번째 Sum 메서드를 선택 합니다.However, overload resolution picks the first Sum method because the conversion to Func<Detail,int> is better than the conversion to Func<Detail,double>.

@No__t-0의 두 번째 호출에서 익명 함수 d => d.UnitPrice * d.UnitCountdouble 형식의 값을 생성 하기 때문에 두 번째 Sum 메서드만 적용 됩니다.In the second invocation of orderDetails.Sum, only the second Sum method is applicable because the anonymous function d => d.UnitPrice * d.UnitCount produces a value of type double. 따라서 오버 로드 확인은 해당 호출에 대 한 두 번째 Sum 메서드를 선택 합니다.Thus, overload resolution picks the second Sum method for that invocation.

익명 함수 및 동적 바인딩Anonymous functions and dynamic binding

익명 함수는 동적으로 바인딩된 작업의 수신자, 인수 또는 피연산자 일 수 없습니다.An anonymous function cannot be a receiver, argument or operand of a dynamically bound operation.

외부 변수Outer variables

Lambda_expression 또는 anonymous_method_expression 를 포함 하는 범위에 있는 모든 지역 변수, 값 매개 변수 또는 매개 변수 배열을 익명 함수의 외부 변수 라고 합니다.Any local variable, value parameter, or parameter array whose scope includes the lambda_expression or anonymous_method_expression is called an outer variable of the anonymous function. 클래스의 인스턴스 함수 멤버에서 this 값은 값 매개 변수로 간주 되며 함수 멤버에 포함 된 익명 함수의 외부 변수입니다.In an instance function member of a class, the this value is considered a value parameter and is an outer variable of any anonymous function contained within the function member.

캡처된 외부 변수Captured outer variables

익명 함수에서 외부 변수를 참조 하는 경우 외부 변수는 무명 함수에 의해 캡처된 것으로 간주 됩니다.When an outer variable is referenced by an anonymous function, the outer variable is said to have been captured by the anonymous function. 일반적으로 지역 변수의 수명은 연결 된 블록 또는 문 (지역 변수)의 실행으로 제한 됩니다.Ordinarily, the lifetime of a local variable is limited to execution of the block or statement with which it is associated (Local variables). 그러나 캡처된 외부 변수의 수명은 익명 함수에서 만든 대리자 또는 식 트리를 가비지 수집에 사용할 수 있을 때까지 최소한으로 확장 됩니다.However, the lifetime of a captured outer variable is extended at least until the delegate or expression tree created from the anonymous function becomes eligible for garbage collection.

예제에서In the example

using System;

delegate int D();

class Test
{
    static D F() {
        int x = 0;
        D result = () => ++x;
        return result;
    }

    static void Main() {
        D d = F();
        Console.WriteLine(d());
        Console.WriteLine(d());
        Console.WriteLine(d());
    }
}

지역 변수 x은 익명 함수에서 캡처되고, x의 수명은 F에서 반환 된 대리자가 가비지 수집에 적격 (프로그램의 끝까지 발생 하지 않음) 될 때까지 최소한으로 확장 됩니다.the local variable x is captured by the anonymous function, and the lifetime of x is extended at least until the delegate returned from F becomes eligible for garbage collection (which doesn't happen until the very end of the program). 익명 함수의 각 호출은 x의 동일한 인스턴스에서 작동 하므로 예제의 출력은 다음과 같습니다.Since each invocation of the anonymous function operates on the same instance of x, the output of the example is:

1
2
3

익명 함수에서 지역 변수 또는 값 매개 변수를 캡처하는 경우 지역 변수 또는 매개 변수는 더 이상 고정 변수 (고정 및 고정 해제 변수)로 간주 되지 않고, 대신에는 이동식 변수로 간주 됩니다.When a local variable or a value parameter is captured by an anonymous function, the local variable or parameter is no longer considered to be a fixed variable (Fixed and moveable variables), but is instead considered to be a moveable variable. 따라서 캡처된 외부 변수의 주소를 사용 하는 모든 unsafe 코드는 먼저 fixed 문을 사용 하 여 변수를 수정 해야 합니다.Thus any unsafe code that takes the address of a captured outer variable must first use the fixed statement to fix the variable.

Uncaptured 변수와 달리 캡처된 지역 변수는 여러 실행 스레드에 동시에 노출 될 수 있습니다.Note that unlike an uncaptured variable, a captured local variable can be simultaneously exposed to multiple threads of execution.

지역 변수 인스턴스화Instantiation of local variables

지역 변수는 실행이 변수의 범위를 시작할 때 인스턴스화되 는 것으로 간주 됩니다.A local variable is considered to be instantiated when execution enters the scope of the variable. 예를 들어, 다음 메서드를 호출 하는 경우 지역 변수 x은 루프의 각 반복에 대해 한 번씩 세 번 인스턴스화되어 초기화 됩니다.For example, when the following method is invoked, the local variable x is instantiated and initialized three times—once for each iteration of the loop.

static void F() {
    for (int i = 0; i < 3; i++) {
        int x = i * 2 + 1;
        ...
    }
}

그러나 x 선언을 루프 밖으로 이동 하면 x의 단일 인스턴스화가 발생 합니다.However, moving the declaration of x outside the loop results in a single instantiation of x:

static void F() {
    int x;
    for (int i = 0; i < 3; i++) {
        x = i * 2 + 1;
        ...
    }
}

캡처되지 않은 경우에는 로컬 변수가 인스턴스화되는 빈도를 정확 하 게 확인할 수 있는 방법이 없습니다. 인스턴스화 수명이 분리 되어 있으므로 각 인스턴스화가 동일한 저장소 위치를 사용 하는 것이 가능 합니다.When not captured, there is no way to observe exactly how often a local variable is instantiated—because the lifetimes of the instantiations are disjoint, it is possible for each instantiation to simply use the same storage location. 그러나 익명 함수에서 지역 변수를 캡처하는 경우 인스턴스화의 영향이 명백 하 게 됩니다.However, when an anonymous function captures a local variable, the effects of instantiation become apparent.

예제The example

using System;

delegate void D();

class Test
{
    static D[] F() {
        D[] result = new D[3];
        for (int i = 0; i < 3; i++) {
            int x = i * 2 + 1;
            result[i] = () => { Console.WriteLine(x); };
        }
        return result;
    }

    static void Main() {
        foreach (D d in F()) d();
    }
}

다음 출력을 생성합니다.produces the output:

1
3
5

그러나 x의 선언이 루프 외부로 이동 하는 경우:However, when the declaration of x is moved outside the loop:

static D[] F() {
    D[] result = new D[3];
    int x;
    for (int i = 0; i < 3; i++) {
        x = i * 2 + 1;
        result[i] = () => { Console.WriteLine(x); };
    }
    return result;
}

출력은 다음과 같습니다.the output is:

5
5
5

For 루프에서 반복 변수를 선언 하는 경우 해당 변수 자체는 루프 외부에서 선언 된 것으로 간주 됩니다.If a for-loop declares an iteration variable, that variable itself is considered to be declared outside of the loop. 따라서 반복 변수 자체를 캡처하도록 예제가 변경 된 경우:Thus, if the example is changed to capture the iteration variable itself:

static D[] F() {
    D[] result = new D[3];
    for (int i = 0; i < 3; i++) {
        result[i] = () => { Console.WriteLine(i); };
    }
    return result;
}

반복 변수의 한 인스턴스만 캡처되고 출력을 생성 합니다.only one instance of the iteration variable is captured, which produces the output:

3
3
3

익명 함수 대리자가 캡처된 일부 변수를 공유 하는 경우에도 다른 다른 인스턴스를 공유할 수 있습니다.It is possible for anonymous function delegates to share some captured variables yet have separate instances of others. 예를 들어 F이로 변경 된 경우For example, if F is changed to

static D[] F() {
    D[] result = new D[3];
    int x = 0;
    for (int i = 0; i < 3; i++) {
        int y = 0;
        result[i] = () => { Console.WriteLine("{0} {1}", ++x, ++y); };
    }
    return result;
}

세 개의 대리자는 동일한 @no__t 인스턴스를 캡처 하지만 y의 개별 인스턴스를 캡처 하므로 출력은 다음과 같습니다.the three delegates capture the same instance of x but separate instances of y, and the output is:

1 1
2 1
3 1

별도의 익명 함수는 외부 변수의 동일한 인스턴스를 캡처할 수 있습니다.Separate anonymous functions can capture the same instance of an outer variable. 예제:In the example:

using System;

delegate void Setter(int value);

delegate int Getter();

class Test
{
    static void Main() {
        int x = 0;
        Setter s = (int value) => { x = value; };
        Getter g = () => { return x; };
        s(5);
        Console.WriteLine(g());
        s(10);
        Console.WriteLine(g());
    }
}

두 익명 함수는 지역 변수의 동일한 인스턴스 x을 캡처하고, 따라서 해당 변수를 통해 "통신" 할 수 있습니다.the two anonymous functions capture the same instance of the local variable x, and they can thus "communicate" through that variable. 예제의 출력은 다음과 같습니다.The output of the example is:

5
10

익명 함수 식의 계산Evaluation of anonymous function expressions

익명 함수 F은 (는) 직접 또는 대리자 생성 식 new D(F)의 실행을 통해 대리자 형식 D 또는 식 트리 형식 E로 변환 되어야 합니다.An anonymous function F must always be converted to a delegate type D or an expression tree type E, either directly or through the execution of a delegate creation expression new D(F). 익명 함수 변환에 설명 된 대로이 변환은 익명 함수의 결과를 결정 합니다.This conversion determines the result of the anonymous function, as described in Anonymous function conversions.

쿼리 식Query expressions

쿼리 식은 관계형 및 계층적 쿼리 언어 (예: SQL 및 XQuery)와 비슷한 쿼리에 대해 언어 통합 구문을 제공 합니다.Query expressions provide a language integrated syntax for queries that is similar to relational and hierarchical query languages such as SQL and XQuery.

query_expression
    : from_clause query_body
    ;

from_clause
    : 'from' type? identifier 'in' expression
    ;

query_body
    : query_body_clauses? select_or_group_clause query_continuation?
    ;

query_body_clauses
    : query_body_clause
    | query_body_clauses query_body_clause
    ;

query_body_clause
    : from_clause
    | let_clause
    | where_clause
    | join_clause
    | join_into_clause
    | orderby_clause
    ;

let_clause
    : 'let' identifier '=' expression
    ;

where_clause
    : 'where' boolean_expression
    ;

join_clause
    : 'join' type? identifier 'in' expression 'on' expression 'equals' expression
    ;

join_into_clause
    : 'join' type? identifier 'in' expression 'on' expression 'equals' expression 'into' identifier
    ;

orderby_clause
    : 'orderby' orderings
    ;

orderings
    : ordering (',' ordering)*
    ;

ordering
    : expression ordering_direction?
    ;

ordering_direction
    : 'ascending'
    | 'descending'
    ;

select_or_group_clause
    : select_clause
    | group_clause
    ;

select_clause
    : 'select' expression
    ;

group_clause
    : 'group' expression 'by' expression
    ;

query_continuation
    : 'into' identifier query_body
    ;

쿼리 식은 from 절로 시작 하 고 select 또는 group 절로 끝납니다.A query expression begins with a from clause and ends with either a select or group clause. 초기 from 절 다음에는 0 개 이상의 from, let, where, @no__t 또는 @no__t 절이 올 수 있습니다.The initial from clause can be followed by zero or more from, let, where, join or orderby clauses. from 절은 시퀀스의 요소에 대 한 범위 변수 를 소개 하는 생성기입니다.Each from clause is a generator introducing a range variable which ranges over the elements of a sequence. let 절은 이전 범위 변수를 사용 하 여 계산 된 값을 나타내는 범위 변수를 도입 합니다.Each let clause introduces a range variable representing a value computed by means of previous range variables. where 절은 결과에서 항목을 제외 하는 필터입니다.Each where clause is a filter that excludes items from the result. join 절은 소스 시퀀스의 지정 된 키를 다른 시퀀스의 키와 비교 하 여 일치 하는 쌍을 생성 합니다.Each join clause compares specified keys of the source sequence with keys of another sequence, yielding matching pairs. orderby 절은 지정 된 조건에 따라 항목의 순서를 다시 지정 합니다. 최종 select 또는 group 절은 범위 변수를 기준으로 결과의 모양을 지정 합니다.Each orderby clause reorders items according to specified criteria.The final select or group clause specifies the shape of the result in terms of the range variables. 마지막으로, 하나의 쿼리 결과를 후속 쿼리의 생성기로 처리 하 여 into 절을 "splice" 쿼리 하는 데 사용할 수 있습니다.Finally, an into clause can be used to "splice" queries by treating the results of one query as a generator in a subsequent query.

쿼리 식의 모호성Ambiguities in query expressions

쿼리 식에는 지정 된 컨텍스트에서 특별 한 의미를 갖는 여러 개의 "상황별 키워드", 즉 식별자가 포함 되어 있습니다.Query expressions contain a number of "contextual keywords", i.e., identifiers that have special meaning in a given context. 특히 from, where, join, on, equals, into, let, orderby, ascending, descending, 0, 1, 2입니다.Specifically these are from, where, join, on, equals, into, let, orderby, ascending, descending, select, group and by. 이러한 식별자를 키워드나 단순한 이름으로 혼합 하 여 발생 하는 쿼리 식의 모호성을 방지 하기 위해 쿼리 식 내에서 발생 하는 경우 이러한 식별자는 키워드로 간주 됩니다.In order to avoid ambiguities in query expressions caused by mixed use of these identifiers as keywords or simple names, these identifiers are considered keywords when occurring anywhere within a query expression.

이러한 목적을 위해 쿼리 식은 "from identifier"으로 시작 하 고 ";", "=" 또는 ","을 제외한 모든 토큰으로 시작 하는 모든 식입니다.For this purpose, a query expression is any expression that starts with "from identifier" followed by any token except ";", "=" or ",".

이러한 단어를 쿼리 식 내에서 식별자로 사용 하기 위해 "@" (식별자) 접두사가 추가 될 수 있습니다.In order to use these words as identifiers within a query expression, they can be prefixed with "@" (Identifiers).

쿼리 식 변환Query expression translation

C# 언어가 쿼리 식의 실행 의미 체계를 지정 하지 않습니다.The C# language does not specify the execution semantics of query expressions. 대신 쿼리 식은 쿼리 식 패턴 (쿼리 식 패턴)을 따르는 메서드의 호출로 변환 됩니다.Rather, query expressions are translated into invocations of methods that adhere to the query expression pattern (The query expression pattern). 특히 쿼리 식은 Where, Select, SelectMany, Join, GroupJoin, OrderBy, OrderByDescending, ThenBy, ThenByDescending, GroupBy 및 0 이라는 메서드의 호출로 변환 됩니다. 이러한 메서드에는 쿼리 식 패턴에 설명 된 대로 특정 시그니처와 결과 형식이 있어야 합니다.Specifically, query expressions are translated into invocations of methods named Where, Select, SelectMany, Join, GroupJoin, OrderBy, OrderByDescending, ThenBy, ThenByDescending, GroupBy, and Cast.These methods are expected to have particular signatures and result types, as described in The query expression pattern. 이러한 메서드는 쿼리 되는 개체의 인스턴스 메서드 이거나 개체 외부에 있는 확장 메서드 일 수 있으며 쿼리의 실제 실행을 구현 합니다.These methods can be instance methods of the object being queried or extension methods that are external to the object, and they implement the actual execution of the query.

쿼리 식에서 메서드 호출로의 변환은 형식 바인딩이나 오버 로드 확인이 수행 되기 전에 발생 하는 구문 매핑입니다.The translation from query expressions to method invocations is a syntactic mapping that occurs before any type binding or overload resolution has been performed. 번역은 구문상 올바르지만 의미상 올바른 C# 코드를 생성 하는 것은 보장 되지 않습니다.The translation is guaranteed to be syntactically correct, but it is not guaranteed to produce semantically correct C# code. 쿼리 식의 다음 변환으로 인해 결과 메서드 호출은 일반 메서드 호출로 처리 되 고,이로 인해 오류가 발생할 수 있습니다. 예를 들어, 메서드가 존재 하지 않는 경우, 인수 형식이 잘못 된 경우, 메서드는 제네릭 및 형식 유추가 실패 합니다.Following translation of query expressions, the resulting method invocations are processed as regular method invocations, and this may in turn uncover errors, for example if the methods do not exist, if arguments have wrong types, or if the methods are generic and type inference fails.

쿼리 식은 더 이상 줄일 수 없을 때까지 다음 번역을 반복 해 서 적용 하 여 처리 됩니다.A query expression is processed by repeatedly applying the following translations until no further reductions are possible. 번역은 응용 프로그램 순서로 나열 됩니다. 각 섹션에서는 이전 섹션의 번역이 철저 하 게 수행 된 것으로 가정 하 고 사용 된 후에는 나중에 동일한 쿼리 식을 처리 하는 동안 섹션을 다시 검토 하지 않습니다.The translations are listed in order of application: each section assumes that the translations in the preceding sections have been performed exhaustively, and once exhausted, a section will not later be revisited in the processing of the same query expression.

쿼리 식에는 범위 변수에 대 한 할당을 사용할 수 없습니다.Assignment to range variables is not allowed in query expressions. 그러나 여기 C# 에 제공 된 구문 변환 체계를 사용 하지 못할 수도 있으므로 구현이 항상이 제한을 적용 하는 것은 허용 되지 않습니다.However a C# implementation is permitted to not always enforce this restriction, since this may sometimes not be possible with the syntactic translation scheme presented here.

특정 번역은 *으로 표시 되는 투명 식별자가 포함 된 범위 변수를 삽입 합니다.Certain translations inject range variables with transparent identifiers denoted by *. 투명 식별자의 특수 속성은 투명 식별자에 추가로 설명 되어 있습니다.The special properties of transparent identifiers are discussed further in Transparent identifiers.

연속을 사용 하 여 Select 및 groupby 절Select and groupby clauses with continuations

연속 작업이 포함 된 쿼리 식A query expression with a continuation

from ... into x ...

다음으로 변환 됩니다.is translated into

from x in ( from ... ) ...

다음 섹션의 번역에서는 쿼리가 @no__t 0으로 연속 되지 않는 것으로 가정 합니다.The translations in the following sections assume that queries have no into continuations.

예제The example

from c in customers
group c by c.Country into g
select new { Country = g.Key, CustCount = g.Count() }

다음으로 변환 됩니다.is translated into

from g in
    from c in customers
    group c by c.Country
select new { Country = g.Key, CustCount = g.Count() }

가 인 최종 변환입니다.the final translation of which is

customers.
GroupBy(c => c.Country).
Select(g => new { Country = g.Key, CustCount = g.Count() })

명시적 범위 변수 형식Explicit range variable types

범위 변수 형식을 명시적으로 지정 하는 from 절입니다.A from clause that explicitly specifies a range variable type

from T x in e

다음으로 변환 됩니다.is translated into

from x in ( e ) . Cast < T > ( )

범위 변수 형식을 명시적으로 지정 하는 join 절입니다.A join clause that explicitly specifies a range variable type

join T x in e on k1 equals k2

다음으로 변환 됩니다.is translated into

join x in ( e ) . Cast < T > ( ) on k1 equals k2

다음 섹션의 번역에서는 쿼리에 명시적 범위 변수 형식이 없다는 것을 전제로 합니다.The translations in the following sections assume that queries have no explicit range variable types.

예제The example

from Customer c in customers
where c.City == "London"
select c

다음으로 변환 됩니다.is translated into

from c in customers.Cast<Customer>()
where c.City == "London"
select c

가 인 최종 변환입니다.the final translation of which is

customers.
Cast<Customer>().
Where(c => c.City == "London")

명시적 범위 변수 형식은 제네릭이 아닌 IEnumerable 인터페이스를 구현 하는 컬렉션을 쿼리 하는 데 유용 하지만 제네릭 IEnumerable<T> 인터페이스가 아닙니다.Explicit range variable types are useful for querying collections that implement the non-generic IEnumerable interface, but not the generic IEnumerable<T> interface. 위의 예제에서 customersArrayList 형식인 경우에 해당 합니다.In the example above, this would be the case if customers were of type ArrayList.

중복 제거 쿼리 식Degenerate query expressions

양식의 쿼리 식입니다.A query expression of the form

from x in e select x

다음으로 변환 됩니다.is translated into

( e ) . Select ( x => x )

예제The example

from c in customers
select c

다음으로 변환 됩니다.is translated into

customers.Select(c => c)

중복 제거 쿼리 식은 일반적으로에서 소스 요소를 선택 하는 식입니다.A degenerate query expression is one that trivially selects the elements of the source. 변환의 이후 단계에서는 다른 변환 단계에서 정의한 중복 제거 쿼리를 원본으로 바꿔서 제거 합니다.A later phase of the translation removes degenerate queries introduced by other translation steps by replacing them with their source. 쿼리의 클라이언트에 대 한 원본의 형식 및 id를 표시 하는 것 처럼 쿼리 식의 결과가 원본 개체 자체가 되지 않도록 하는 것이 중요 합니다.It is important however to ensure that the result of a query expression is never the source object itself, as that would reveal the type and identity of the source to the client of the query. 따라서이 단계에서는 소스에서 Select을 명시적으로 호출 하 여 소스 코드에서 직접 작성 한 중복 제거 쿼리를 보호 합니다.Therefore this step protects degenerate queries written directly in source code by explicitly calling Select on the source. 그런 다음 Select 및 기타 쿼리 연산자의 구현자는 이러한 메서드가 소스 개체 자체를 반환 하지 않도록 합니다.It is then up to the implementers of Select and other query operators to ensure that these methods never return the source object itself.

From, let, where, join 및 orderby 절From, let, where, join and orderby clauses

두 번째 from 절이 있고 그 뒤에 select 절이 있는 쿼리 식A query expression with a second from clause followed by a select clause

from x1 in e1
from x2 in e2
select v

다음으로 변환 됩니다.is translated into

( e1 ) . SelectMany( x1 => e2 , ( x1 , x2 ) => v )

@No__t-1 절이 뒤에 오는 두 번째 from 절이 있는 쿼리 식입니다.A query expression with a second from clause followed by something other than a select clause:

from x1 in e1
from x2 in e2
...

다음으로 변환 됩니다.is translated into

from * in ( e1 ) . SelectMany( x1 => e2 , ( x1 , x2 ) => new { x1 , x2 } )
...

@No__t-0 절이 있는 쿼리 식A query expression with a let clause

from x in e
let y = f
...

다음으로 변환 됩니다.is translated into

from * in ( e ) . Select ( x => new { x , y = f } )
...

@No__t-0 절이 있는 쿼리 식A query expression with a where clause

from x in e
where f
...

다음으로 변환 됩니다.is translated into

from x in ( e ) . Where ( x => f )
...

@No__t-1이 없고 select 절이 뒤에 join 절이 있는 쿼리 식A query expression with a join clause without an into followed by a select clause

from x1 in e1
join x2 in e2 on k1 equals k2
select v

다음으로 변환 됩니다.is translated into

( e1 ) . Join( e2 , x1 => k1 , x2 => k2 , ( x1 , x2 ) => v )

@No__t-1이 없고 select 절이 아닌 join 절이 있는 쿼리 식A query expression with a join clause without an into followed by something other than a select clause

from x1 in e1
join x2 in e2 on k1 equals k2
...

다음으로 변환 됩니다.is translated into

from * in ( e1 ) . Join( e2 , x1 => k1 , x2 => k2 , ( x1 , x2 ) => new { x1 , x2 })
...

@No__t-1이 뒤에 select 절이 있는 join 절이 있는 쿼리 식A query expression with a join clause with an into followed by a select clause

from x1 in e1
join x2 in e2 on k1 equals k2 into g
select v

다음으로 변환 됩니다.is translated into

( e1 ) . GroupJoin( e2 , x1 => k1 , x2 => k2 , ( x1 , g ) => v )

@No__t-1을 사용 하는 join 절과 select 절이 아닌 쿼리 식A query expression with a join clause with an into followed by something other than a select clause

from x1 in e1
join x2 in e2 on k1 equals k2 into g
...

다음으로 변환 됩니다.is translated into

from * in ( e1 ) . GroupJoin( e2 , x1 => k1 , x2 => k2 , ( x1 , g ) => new { x1 , g })
...

@No__t-0 절이 있는 쿼리 식A query expression with an orderby clause

from x in e
orderby k1 , k2 , ..., kn
...

다음으로 변환 됩니다.is translated into

from x in ( e ) . 
OrderBy ( x => k1 ) . 
ThenBy ( x => k2 ) .
... .
ThenBy ( x => kn )
...

정렬 절이 descending 방향 표시기를 지정 하는 경우에는 OrderByDescending 또는 ThenByDescending의 호출이 대신 생성 됩니다.If an ordering clause specifies a descending direction indicator, an invocation of OrderByDescending or ThenByDescending is produced instead.

다음 번역에서는 let, where, join 또는 orderby 절이 없고 각 쿼리 식에서 하나의 초기 from 절이 아닌 것으로 가정 합니다.The following translations assume that there are no let, where, join or orderby clauses, and no more than the one initial from clause in each query expression.

예제The example

from c in customers
from o in c.Orders
select new { c.Name, o.OrderID, o.Total }

다음으로 변환 됩니다.is translated into

customers.
SelectMany(c => c.Orders,
     (c,o) => new { c.Name, o.OrderID, o.Total }
)

예제The example

from c in customers
from o in c.Orders
orderby o.Total descending
select new { c.Name, o.OrderID, o.Total }

다음으로 변환 됩니다.is translated into

from * in customers.
    SelectMany(c => c.Orders, (c,o) => new { c, o })
orderby o.Total descending
select new { c.Name, o.OrderID, o.Total }

가 인 최종 변환입니다.the final translation of which is

customers.
SelectMany(c => c.Orders, (c,o) => new { c, o }).
OrderByDescending(x => x.o.Total).
Select(x => new { x.c.Name, x.o.OrderID, x.o.Total })

여기서 x은 표시 되지 않고 액세스할 수 없는 컴파일러 생성 식별자입니다.where x is a compiler generated identifier that is otherwise invisible and inaccessible.

예제The example

from o in orders
let t = o.Details.Sum(d => d.UnitPrice * d.Quantity)
where t >= 1000
select new { o.OrderID, Total = t }

다음으로 변환 됩니다.is translated into

from * in orders.
    Select(o => new { o, t = o.Details.Sum(d => d.UnitPrice * d.Quantity) })
where t >= 1000 
select new { o.OrderID, Total = t }

가 인 최종 변환입니다.the final translation of which is

orders.
Select(o => new { o, t = o.Details.Sum(d => d.UnitPrice * d.Quantity) }).
Where(x => x.t >= 1000).
Select(x => new { x.o.OrderID, Total = x.t })

여기서 x은 표시 되지 않고 액세스할 수 없는 컴파일러 생성 식별자입니다.where x is a compiler generated identifier that is otherwise invisible and inaccessible.

예제The example

from c in customers
join o in orders on c.CustomerID equals o.CustomerID
select new { c.Name, o.OrderDate, o.Total }

다음으로 변환 됩니다.is translated into

customers.Join(orders, c => c.CustomerID, o => o.CustomerID,
    (c, o) => new { c.Name, o.OrderDate, o.Total })

예제The example

from c in customers
join o in orders on c.CustomerID equals o.CustomerID into co
let n = co.Count()
where n >= 10
select new { c.Name, OrderCount = n }

다음으로 변환 됩니다.is translated into

from * in customers.
    GroupJoin(orders, c => c.CustomerID, o => o.CustomerID,
        (c, co) => new { c, co })
let n = co.Count()
where n >= 10 
select new { c.Name, OrderCount = n }

가 인 최종 변환입니다.the final translation of which is

customers.
GroupJoin(orders, c => c.CustomerID, o => o.CustomerID,
    (c, co) => new { c, co }).
Select(x => new { x, n = x.co.Count() }).
Where(y => y.n >= 10).
Select(y => new { y.x.c.Name, OrderCount = y.n)

여기서 xy은 컴파일러에서 생성 되 고, 그렇지 않은 경우에는 액세스할 수 없는 식별자입니다.where x and y are compiler generated identifiers that are otherwise invisible and inaccessible.

예제The example

from o in orders
orderby o.Customer.Name, o.Total descending
select o

최종 번역 있음has the final translation

orders.
OrderBy(o => o.Customer.Name).
ThenByDescending(o => o.Total)

Select 절Select clauses

양식의 쿼리 식입니다.A query expression of the form

from x in e select v

다음으로 변환 됩니다.is translated into

( e ) . Select ( x => v )

v가 식별자 x 인 경우를 제외 하 고는 단순히except when v is the identifier x, the translation is simply

( e )

For example

from c in customers.Where(c => c.City == "London")
select c

단순히로 변환 됩니다.is simply translated into

customers.Where(c => c.City == "London")

Groupby 절Groupby clauses

양식의 쿼리 식입니다.A query expression of the form

from x in e group v by k

다음으로 변환 됩니다.is translated into

( e ) . GroupBy ( x => k , x => v )

v가 식별자 x 인 경우를 제외 하 고, 변환은except when v is the identifier x, the translation is

( e ) . GroupBy ( x => k )

예제The example

from c in customers
group c.Name by c.Country

다음으로 변환 됩니다.is translated into

customers.
GroupBy(c => c.Country, c => c.Name)

투명 식별자Transparent identifiers

특정 번역은 *로 표시 되는 투명 식별자 가 포함 된 범위 변수를 삽입 합니다.Certain translations inject range variables with transparent identifiers denoted by *. 투명 식별자는 적절 한 언어 기능이 아닙니다. 쿼리 식 변환 프로세스에서 중간 단계로만 존재 합니다.Transparent identifiers are not a proper language feature; they exist only as an intermediate step in the query expression translation process.

쿼리 변환이 투명 식별자를 삽입 하면 추가 변환 단계가 투명 식별자를 익명 함수 및 익명 개체 이니셜라이저에 전파 합니다.When a query translation injects a transparent identifier, further translation steps propagate the transparent identifier into anonymous functions and anonymous object initializers. 이러한 컨텍스트에서 투명 식별자는 다음과 같은 동작을 수행 합니다.In those contexts, transparent identifiers have the following behavior:

  • 투명 식별자가 익명 함수에서 매개 변수로 발생 하면 연결 된 익명 형식의 멤버는 익명 함수의 본문에서 자동으로 범위에 있습니다.When a transparent identifier occurs as a parameter in an anonymous function, the members of the associated anonymous type are automatically in scope in the body of the anonymous function.
  • 투명 식별자가 있는 멤버가 범위 내에 있는 경우 해당 멤버의 멤버도 범위 내에 있습니다.When a member with a transparent identifier is in scope, the members of that member are in scope as well.
  • 투명 식별자가 익명 개체 이니셜라이저에서 멤버 선언 자로 발생 하는 경우 투명 식별자가 포함 된 멤버를 소개 합니다.When a transparent identifier occurs as a member declarator in an anonymous object initializer, it introduces a member with a transparent identifier.
  • 위에서 설명한 변환 단계에서 투명 식별자는 여러 범위 변수를 단일 개체의 멤버로 캡처할 목적으로 항상 익명 형식과 함께 도입 됩니다.In the translation steps described above, transparent identifiers are always introduced together with anonymous types, with the intent of capturing multiple range variables as members of a single object. 의 C# 구현은 여러 범위 변수를 그룹화 하기 위해 익명 형식과 다른 메커니즘을 사용할 수 있습니다.An implementation of C# is permitted to use a different mechanism than anonymous types to group together multiple range variables. 다음 변환 예제에서는 익명 형식이 사용 되는 것으로 가정 하 고 투명 식별자를 변환 하는 방법을 보여 줍니다.The following translation examples assume that anonymous types are used, and show how transparent identifiers can be translated away.

예제The example

from c in customers
from o in c.Orders
orderby o.Total descending
select new { c.Name, o.Total }

다음으로 변환 됩니다.is translated into

from * in customers.
    SelectMany(c => c.Orders, (c,o) => new { c, o })
orderby o.Total descending
select new { c.Name, o.Total }

다음으로 변환 됩니다.which is further translated into

customers.
SelectMany(c => c.Orders, (c,o) => new { c, o }).
OrderByDescending(* => o.Total).
Select(* => new { c.Name, o.Total })

투명 식별자가 지워진 경우는와 동일 합니다.which, when transparent identifiers are erased, is equivalent to

customers.
SelectMany(c => c.Orders, (c,o) => new { c, o }).
OrderByDescending(x => x.o.Total).
Select(x => new { x.c.Name, x.o.Total })

여기서 x은 표시 되지 않고 액세스할 수 없는 컴파일러 생성 식별자입니다.where x is a compiler generated identifier that is otherwise invisible and inaccessible.

예제The example

from c in customers
join o in orders on c.CustomerID equals o.CustomerID
join d in details on o.OrderID equals d.OrderID
join p in products on d.ProductID equals p.ProductID
select new { c.Name, o.OrderDate, p.ProductName }

다음으로 변환 됩니다.is translated into

from * in customers.
    Join(orders, c => c.CustomerID, o => o.CustomerID, 
        (c, o) => new { c, o })
join d in details on o.OrderID equals d.OrderID
join p in products on d.ProductID equals p.ProductID
select new { c.Name, o.OrderDate, p.ProductName }

다음으로 축소 됩니다.which is further reduced to

customers.
Join(orders, c => c.CustomerID, o => o.CustomerID, (c, o) => new { c, o }).
Join(details, * => o.OrderID, d => d.OrderID, (*, d) => new { *, d }).
Join(products, * => d.ProductID, p => p.ProductID, (*, p) => new { *, p }).
Select(* => new { c.Name, o.OrderDate, p.ProductName })

가 인 최종 변환입니다.the final translation of which is

customers.
Join(orders, c => c.CustomerID, o => o.CustomerID,
    (c, o) => new { c, o }).
Join(details, x => x.o.OrderID, d => d.OrderID,
    (x, d) => new { x, d }).
Join(products, y => y.d.ProductID, p => p.ProductID,
    (y, p) => new { y, p }).
Select(z => new { z.y.x.c.Name, z.y.x.o.OrderDate, z.p.ProductName })

여기서 x, y, z는 컴파일러에서 생성 되며,이 식별자는 표시 되지 않고 액세스할 수 없습니다.where x, y, and z are compiler generated identifiers that are otherwise invisible and inaccessible.

쿼리 식 패턴The query expression pattern

쿼리 식 패턴 은 형식에서 쿼리 식을 지원 하기 위해 구현할 수 있는 메서드의 패턴을 설정 합니다.The Query expression pattern establishes a pattern of methods that types can implement to support query expressions. 쿼리 식은 구문 매핑을 통해 메서드 호출로 변환 되기 때문에 형식은 쿼리 식 패턴을 구현 하는 방법에 상당한 유연성을 갖습니다.Because query expressions are translated to method invocations by means of a syntactic mapping, types have considerable flexibility in how they implement the query expression pattern. 예를 들어, 패턴의 메서드는 두 개의 호출 구문이 동일 하기 때문에 인스턴스 메서드 또는 확장 메서드로 구현 될 수 있으며, 무명 함수는 둘 다로 변환할 수 있기 때문에 메서드는 대리자나 식 트리를 요청할 수 있습니다.For example, the methods of the pattern can be implemented as instance methods or as extension methods because the two have the same invocation syntax, and the methods can request delegates or expression trees because anonymous functions are convertible to both.

쿼리 식 패턴을 지 원하는 제네릭 형식 C<T>의 권장 셰이프는 다음과 같습니다.The recommended shape of a generic type C<T> that supports the query expression pattern is shown below. 제네릭 형식은 매개 변수와 결과 형식 간의 적절 한 관계를 보여 주기 위해 사용 되지만 제네릭이 아닌 형식에 대해서도 패턴을 구현할 수 있습니다.A generic type is used in order to illustrate the proper relationships between parameter and result types, but it is possible to implement the pattern for non-generic types as well.

delegate R Func<T1,R>(T1 arg1);

delegate R Func<T1,T2,R>(T1 arg1, T2 arg2);

class C
{
    public C<T> Cast<T>();
}

class C<T> : C
{
    public C<T> Where(Func<T,bool> predicate);

    public C<U> Select<U>(Func<T,U> selector);

    public C<V> SelectMany<U,V>(Func<T,C<U>> selector,
        Func<T,U,V> resultSelector);

    public C<V> Join<U,K,V>(C<U> inner, Func<T,K> outerKeySelector,
        Func<U,K> innerKeySelector, Func<T,U,V> resultSelector);

    public C<V> GroupJoin<U,K,V>(C<U> inner, Func<T,K> outerKeySelector,
        Func<U,K> innerKeySelector, Func<T,C<U>,V> resultSelector);

    public O<T> OrderBy<K>(Func<T,K> keySelector);

    public O<T> OrderByDescending<K>(Func<T,K> keySelector);

    public C<G<K,T>> GroupBy<K>(Func<T,K> keySelector);

    public C<G<K,E>> GroupBy<K,E>(Func<T,K> keySelector,
        Func<T,E> elementSelector);
}

class O<T> : C<T>
{
    public O<T> ThenBy<K>(Func<T,K> keySelector);

    public O<T> ThenByDescending<K>(Func<T,K> keySelector);
}

class G<K,T> : C<T>
{
    public K Key { get; }
}

위의 메서드는 제네릭 대리자 형식 Func<T1,R>Func<T1,T2,R>을 사용 하지만, 매개 변수 및 결과 형식에서 동일한 관계를 사용 하 여 다른 대리자 또는 식 트리 형식을 동일 하 게 사용할 수 있습니다.The methods above use the generic delegate types Func<T1,R> and Func<T1,T2,R>, but they could equally well have used other delegate or expression tree types with the same relationships in parameter and result types.

@No__t-0과 O<T> 사이에 권장 되는 관계를 사용 하 여 ThenByThenByDescending 메서드를 @no__t @no__t 결과에만 사용할 수 있도록 합니다.Notice the recommended relationship between C<T> and O<T> which ensures that the ThenBy and ThenByDescending methods are available only on the result of an OrderBy or OrderByDescending. 또한 GroupBy의 권장 되는 셰이프를 확인 합니다. 시퀀스 시퀀스는 각 내부 시퀀스에 추가 Key 속성이 있습니다.Also notice the recommended shape of the result of GroupBy -- a sequence of sequences, where each inner sequence has an additional Key property.

@No__t-0 네임 스페이스는 System.Collections.Generic.IEnumerable<T> 인터페이스를 구현 하는 모든 형식에 대해 쿼리 연산자 패턴의 구현을 제공 합니다.The System.Linq namespace provides an implementation of the query operator pattern for any type that implements the System.Collections.Generic.IEnumerable<T> interface.

대입 연산자Assignment operators

할당 연산자는 변수, 속성, 이벤트 또는 인덱서 요소에 새 값을 할당 합니다.The assignment operators assign a new value to a variable, a property, an event, or an indexer element.

assignment
    : unary_expression assignment_operator expression
    ;

assignment_operator
    : '='
    | '+='
    | '-='
    | '*='
    | '/='
    | '%='
    | '&='
    | '|='
    | '^='
    | '<<='
    | right_shift_assignment
    ;

할당의 왼쪽 피연산자는 변수, 속성 액세스, 인덱서 액세스 또는 이벤트 액세스로 분류 된 식 이어야 합니다.The left operand of an assignment must be an expression classified as a variable, a property access, an indexer access, or an event access.

@No__t-0 연산자를 단순 할당 연산자라고 합니다.The = operator is called the simple assignment operator. 왼쪽 피연산자가 제공 하는 변수, 속성 또는 인덱서 요소에 오른쪽 피연산자의 값을 할당 합니다.It assigns the value of the right operand to the variable, property, or indexer element given by the left operand. 단순 할당 연산자의 왼쪽 피연산자는 이벤트 액세스 일 수 없습니다 ( 필드와 유사한 이벤트에 설명 된 경우 제외).The left operand of the simple assignment operator may not be an event access (except as described in Field-like events). 단순 할당 연산자는 단순 할당에 설명 되어 있습니다.The simple assignment operator is described in Simple assignment.

@No__t-0 연산자가 아닌 대입 연산자를 복합 할당 연산자라고 합니다.The assignment operators other than the = operator are called the compound assignment operators. 이러한 연산자는 두 피연산자에 대해 표시 된 작업을 수행 하 고 결과 값을 왼쪽 피연산자가 제공 하는 변수, 속성 또는 인덱서 요소에 할당 합니다.These operators perform the indicated operation on the two operands, and then assign the resulting value to the variable, property, or indexer element given by the left operand. 복합 할당 연산자는 복합 할당에 설명 되어 있습니다.The compound assignment operators are described in Compound assignment.

이벤트 액세스 식을 왼쪽 피연산자로 사용 하는 +=-= 연산자를 이벤트 할당 연산자라고 합니다.The += and -= operators with an event access expression as the left operand are called the event assignment operators. 왼쪽 피연산자 인 이벤트 액세스와 함께 사용할 수 있는 다른 할당 연산자가 없습니다.No other assignment operator is valid with an event access as the left operand. 이벤트 할당 연산자는 이벤트 할당에 설명 되어 있습니다.The event assignment operators are described in Event assignment.

할당 연산자는 오른쪽 결합성이 있습니다. 즉, 작업은 오른쪽에서 왼쪽으로 그룹화 됩니다.The assignment operators are right-associative, meaning that operations are grouped from right to left. 예를 들어 a = b = c 형식의 식은 a = (b = c)로 계산 됩니다.For example, an expression of the form a = b = c is evaluated as a = (b = c).

단순 할당Simple assignment

@No__t-0 연산자를 단순 할당 연산자 라고 합니다.The = operator is called the simple assignment operator.

단순 할당의 왼쪽 피연산자의 형식이 E.P 또는 E[Ei]입니다. 여기서 E는 컴파일 시간 형식이-3 @no__t 경우 할당은 동적으로 바인딩됩니다 (동적 바인딩).If the left operand of a simple assignment is of the form E.P or E[Ei] where E has the compile-time type dynamic, then the assignment is dynamically bound (Dynamic binding). 이 경우 할당 식의 컴파일 시간 형식은 dynamic이 고, 아래에서 설명 하는 해결 방법은 E의 런타임 형식을 기반으로 런타임 시 수행 됩니다.In this case the compile-time type of the assignment expression is dynamic, and the resolution described below will take place at run-time based on the run-time type of E.

간단한 할당에서 오른쪽 피연산자는 왼쪽 피연산자의 형식으로 암시적으로 변환할 수 있는 식 이어야 합니다.In a simple assignment, the right operand must be an expression that is implicitly convertible to the type of the left operand. 작업은 오른쪽 피연산자의 값을 왼쪽 피연산자가 제공 하는 변수, 속성 또는 인덱서 요소에 할당 합니다.The operation assigns the value of the right operand to the variable, property, or indexer element given by the left operand.

단순 대입 식의 결과는 왼쪽 피연산자에 할당 된 값입니다.The result of a simple assignment expression is the value assigned to the left operand. 결과는 왼쪽 피연산자와 형식이 같으며 항상 값으로 분류 됩니다.The result has the same type as the left operand and is always classified as a value.

왼쪽 피연산자가 속성 또는 인덱서 액세스 인 경우 속성 또는 인덱서에 set 접근자가 있어야 합니다.If the left operand is a property or indexer access, the property or indexer must have a set accessor. 이러한 경우가 아니면 바인딩 시간 오류가 발생 합니다.If this is not the case, a binding-time error occurs.

@No__t-0 폼의 단순 할당에 대 한 런타임 처리는 다음 단계로 구성 됩니다.The run-time processing of a simple assignment of the form x = y consists of the following steps:

  • @No__t-0은 변수로 분류 됩니다.If x is classified as a variable:
    • x을 계산 하 여 변수를 생성 합니다.x is evaluated to produce the variable.
    • y이 계산 되 고, 필요한 경우 암시적 변환 (암시적 변환)을 통해-1 @no__t 형식으로 변환 됩니다.y is evaluated and, if required, converted to the type of x through an implicit conversion (Implicit conversions).
    • @No__t-0으로 지정 된 변수가 reference_type의 배열 요소인 경우에는 y에 대해 계산 된 값이 요소 x 인 배열 인스턴스와 호환 되도록 런타임 검사가 수행 됩니다.If the variable given by x is an array element of a reference_type, a run-time check is performed to ensure that the value computed for y is compatible with the array instance of which x is an element. @No__t-0이-1 @no__t 이거나 암시적 참조 변환 (암시적 참조 변환)이 y에서 참조 하는 인스턴스의 실제 형식에서-4 @no__t를 포함 하는 배열 인스턴스의 실제 요소 형식으로 존재 하는 경우 확인이 성공 합니다.The check succeeds if y is null, or if an implicit reference conversion (Implicit reference conversions) exists from the actual type of the instance referenced by y to the actual element type of the array instance containing x. 그렇지 않으면 System.ArrayTypeMismatchException이 throw됩니다.Otherwise, a System.ArrayTypeMismatchException is thrown.
    • @No__t-0의 평가 및 변환 결과로 생성 된 값은 x의 계산에 의해 지정 된 위치에 저장 됩니다.The value resulting from the evaluation and conversion of y is stored into the location given by the evaluation of x.
  • @No__t-0은 속성 또는 인덱서 액세스로 분류 됩니다.If x is classified as a property or indexer access:
    • 인스턴스 식 (xstatic이 아닌 경우) 및 x과 연결 된 인수 목록 (x가 인덱서 액세스 인 경우)이 평가 되 고 이후 set 접근자 호출에서 결과가 사용 됩니다.The instance expression (if x is not static) and the argument list (if x is an indexer access) associated with x are evaluated, and the results are used in the subsequent set accessor invocation.
    • y이 계산 되 고, 필요한 경우 암시적 변환 (암시적 변환)을 통해-1 @no__t 형식으로 변환 됩니다.y is evaluated and, if required, converted to the type of x through an implicit conversion (Implicit conversions).
    • @No__t-1의 set 접근자는 value 인수로 y에 대해 계산 된 값을 사용 하 여 호출 됩니다.The set accessor of x is invoked with the value computed for y as its value argument.

배열 분산 규칙 (배열 공분산)은 B에서 A로의 암시적 참조 변환이 있는 경우-1의 배열 형식에 @no__t 대 한 참조가 A[] 인 배열 형식의 값을 허용 합니다.The array co-variance rules (Array covariance) permit a value of an array type A[] to be a reference to an instance of an array type B[], provided an implicit reference conversion exists from B to A. 이러한 규칙으로 인해 reference_type 의 배열 요소에 할당 하려면 런타임 검사를 수행 하 여 할당 된 값이 배열 인스턴스와 호환 되는지 확인 해야 합니다.Because of these rules, assignment to an array element of a reference_type requires a run-time check to ensure that the value being assigned is compatible with the array instance. 예제에서In the example

string[] sa = new string[10];
object[] oa = sa;

oa[0] = null;               // Ok
oa[1] = "Hello";            // Ok
oa[2] = new ArrayList();    // ArrayTypeMismatchException

ArrayList의 인스턴스를 string[]의 요소에 저장할 수 없기 때문에 마지막 할당으로 인해 System.ArrayTypeMismatchException이 throw 됩니다.the last assignment causes a System.ArrayTypeMismatchException to be thrown because an instance of ArrayList cannot be stored in an element of a string[].

Struct_type 에 선언 된 속성이 나 인덱서가 할당의 대상인 경우에는 속성 또는 인덱서 액세스와 연결 된 인스턴스 식이 변수로 분류 되어야 합니다.When a property or indexer declared in a struct_type is the target of an assignment, the instance expression associated with the property or indexer access must be classified as a variable. 인스턴스 식이 값으로 분류 되는 경우 바인딩 시간 오류가 발생 합니다.If the instance expression is classified as a value, a binding-time error occurs. 멤버 액세스로 인해 필드에도 동일한 규칙이 적용 됩니다.Because of Member access, the same rule also applies to fields.

선언 된 경우:Given the declarations:

struct Point
{
    int x, y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int X {
        get { return x; }
        set { x = value; }
    }

    public int Y {
        get { return y; }
        set { y = value; }
    }
}

struct Rectangle
{
    Point a, b;

    public Rectangle(Point a, Point b) {
        this.a = a;
        this.b = b;
    }

    public Point A {
        get { return a; }
        set { a = value; }
    }

    public Point B {
        get { return b; }
        set { b = value; }
    }
}

예제에서in the example

Point p = new Point();
p.X = 100;
p.Y = 100;
Rectangle r = new Rectangle();
r.A = new Point(10, 10);
r.B = p;

p.X, p.Y, r.Ar.B에 대 한 할당은 pr가 변수 이므로 허용 됩니다.the assignments to p.X, p.Y, r.A, and r.B are permitted because p and r are variables. 그러나 예제에서는However, in the example

Rectangle r = new Rectangle();
r.A.X = 10;
r.A.Y = 10;
r.B.X = 100;
r.B.Y = 100;

r.Ar.B은 변수가 아니기 때문에 할당은 모두 유효 하지 않습니다.the assignments are all invalid, since r.A and r.B are not variables.

복합 할당Compound assignment

복합 할당의 왼쪽 피연산자의 형식이 E.P 또는 E[Ei]입니다. 여기서 E는 컴파일 타임 형식이-3 @no__t 경우 할당은 동적으로 바인딩됩니다 (동적 바인딩).If the left operand of a compound assignment is of the form E.P or E[Ei] where E has the compile-time type dynamic, then the assignment is dynamically bound (Dynamic binding). 이 경우 할당 식의 컴파일 시간 형식은 dynamic이 고, 아래에서 설명 하는 해결 방법은 E의 런타임 형식을 기반으로 런타임 시 수행 됩니다.In this case the compile-time type of the assignment expression is dynamic, and the resolution described below will take place at run-time based on the run-time type of E.

@No__t-0 형식의 작업은 작업이 @no__t 작성 된 것 처럼 이진 연산자 오버 로드 확인 (이진 연산자 오버 로드 확인)을 적용 하 여 처리 됩니다.An operation of the form x op= y is processed by applying binary operator overload resolution (Binary operator overload resolution) as if the operation was written x op y. 다음Then,

  • 선택한 연산자의 반환 형식을 암시적으로 x 형식으로 변환할 수 있는 경우에는 x가 한 번만 계산 된다는 점을 제외 하면 작업이 x = x op y로 평가 됩니다.If the return type of the selected operator is implicitly convertible to the type of x, the operation is evaluated as x = x op y, except that x is evaluated only once.
  • 선택한 연산자가 미리 정의 된 연산자 인 경우 선택한 연산자의 반환 형식을 x의 형식으로 명시적으로 변환할 수 있고 yx 형식으로 암시적으로 변환할 수 있으면이 고, 연산자는 시프트 연산자 인 경우입니다. 작업은 x = (T)(x op y)으로 계산 됩니다. @no__t 여기서-6은 x이 한 번만 계산 된다는 점을 제외 하 고-4는 x의 유형입니다.Otherwise, if the selected operator is a predefined operator, if the return type of the selected operator is explicitly convertible to the type of x, and if y is implicitly convertible to the type of x or the operator is a shift operator, then the operation is evaluated as x = (T)(x op y), where T is the type of x, except that x is evaluated only once.
  • 그렇지 않으면 복합 할당은 유효 하지 않으며 바인딩 타임 오류가 발생 합니다.Otherwise, the compound assignment is invalid, and a binding-time error occurs.

"한 번만 평가" 라는 용어는-0을 @no__t 계산 하는 경우 x의 구성 식 결과가 일시적으로 저장 된 후 x에 대 한 할당을 수행할 때 다시 사용 됨을 의미 합니다.The term "evaluated only once" means that in the evaluation of x op y, the results of any constituent expressions of x are temporarily saved and then reused when performing the assignment to x. 예를 들어 A()[B()] += C() 할당에서 Aint[]를 반환 하는 메서드이 고 BCint를 반환 하는 메서드인 경우, 메서드는 A, B, C 순서로 한 번만 호출 됩니다.For example, in the assignment A()[B()] += C(), where A is a method returning int[], and B and C are methods returning int, the methods are invoked only once, in the order A, B, C.

복합 할당의 왼쪽 피연산자가 속성 액세스 또는 인덱서 액세스 인 경우 속성 또는 인덱서에 get 접근자와 set 접근자가 둘 다 있어야 합니다.When the left operand of a compound assignment is a property access or indexer access, the property or indexer must have both a get accessor and a set accessor. 이러한 경우가 아니면 바인딩 시간 오류가 발생 합니다.If this is not the case, a binding-time error occurs.

위의 두 번째 규칙에서는 특정 컨텍스트에서 x op= yx = (T)(x op y)로 평가할 수 있습니다.The second rule above permits x op= y to be evaluated as x = (T)(x op y) in certain contexts. 이 규칙은 왼쪽 피연산자가 sbyte, byte, short, ushort 또는 char 형식일 때 미리 정의 된 연산자를 복합 연산자로 사용할 수 있도록 하기 위해 존재 합니다.The rule exists such that the predefined operators can be used as compound operators when the left operand is of type sbyte, byte, short, ushort, or char. 두 인수가 모두 이러한 형식 중 하나인 경우에도 미리 정의 된 연산자는 이진 숫자 승격에 설명 된 대로 int 형식의 결과를 생성 합니다.Even when both arguments are of one of those types, the predefined operators produce a result of type int, as described in Binary numeric promotions. 따라서 캐스트를 사용 하지 않으면 결과를 왼쪽 피연산자에 할당할 수 없습니다.Thus, without a cast it would not be possible to assign the result to the left operand.

미리 정의 된 연산자에 대 한 규칙의 직관적인 효과는 x op yx = y를 모두 허용 하는 경우 x op= y이 허용 된다는 것입니다.The intuitive effect of the rule for predefined operators is simply that x op= y is permitted if both of x op y and x = y are permitted. 예제에서In the example

byte b = 0;
char ch = '\0';
int i = 0;

b += 1;             // Ok
b += 1000;          // Error, b = 1000 not permitted
b += i;             // Error, b = i not permitted
b += (byte)i;       // Ok

ch += 1;            // Error, ch = 1 not permitted
ch += (char)1;      // Ok

각 오류에 대 한 직관적인 이유는 해당 하는 단순 할당 에서도 오류가 발생 하기 때문입니다.the intuitive reason for each error is that a corresponding simple assignment would also have been an error.

이는 복합 할당 작업이 리프트 된 작업을 지원 함을 의미 하기도 합니다.This also means that compound assignment operations support lifted operations. 예제에서In the example

int? i = 0;
i += 1;             // Ok

리프트 된 연산자 +(int?,int?)이 사용 됩니다.the lifted operator +(int?,int?) is used.

이벤트 할당Event assignment

@No__t-0 또는 -= 연산자의 왼쪽 피연산자가 이벤트 액세스로 분류 된 경우 식은 다음과 같이 계산 됩니다.If the left operand of a += or -= operator is classified as an event access, then the expression is evaluated as follows:

  • 이벤트 액세스의 인스턴스 식 (있는 경우)이 계산 됩니다.The instance expression, if any, of the event access is evaluated.
  • @No__t-0 또는 -= 연산자의 오른쪽 피연산자가 계산 되 고, 필요한 경우 암시적 변환 (암시적 변환)을 통해 왼쪽 피연산자의 형식으로 변환 됩니다.The right operand of the += or -= operator is evaluated, and, if required, converted to the type of the left operand through an implicit conversion (Implicit conversions).
  • 계산 후와 필요한 경우 변환 후 오른쪽 피연산자로 구성 된 인수 목록을 사용 하 여 이벤트의 이벤트 접근자가 호출 됩니다.An event accessor of the event is invoked, with argument list consisting of the right operand, after evaluation and, if necessary, conversion. 연산자가 0 @no__t 된 경우 add 접근자가 호출 됩니다. 연산자가-2 @no__t 된 경우 remove 접근자가 호출 됩니다.If the operator was +=, the add accessor is invoked; if the operator was -=, the remove accessor is invoked.

이벤트 할당 식은 값을 생성 하지 않습니다.An event assignment expression does not yield a value. 따라서 이벤트 할당 식은 statement_expression (식 문)의 컨텍스트에서만 유효 합니다.Thus, an event assignment expression is valid only in the context of a statement_expression (Expression statements).

Expression

식은 non_assignment_expression 또는 할당입니다.An expression is either a non_assignment_expression or an assignment.

expression
    : non_assignment_expression
    | assignment
    ;

non_assignment_expression
    : conditional_expression
    | lambda_expression
    | query_expression
    ;

상수 식Constant expressions

Constant_expression 는 컴파일 시간에 완전히 계산 될 수 있는 식입니다.A constant_expression is an expression that can be fully evaluated at compile-time.

constant_expression
    : expression
    ;

상수 식은 다음 형식 중 하나를 사용 하는 @no__t 0 리터럴 또는 값 이어야 합니다. sbyte, byte, short, ushort, int, uint, long, ulong, char, 0, 1, 2, 3, 4 , 5 또는 모든 열거형 형식입니다.A constant expression must be the null literal or a value with one of the following types: sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool, object, string, or any enumeration type. 상수 식에는 다음 구문만 사용할 수 있습니다.Only the following constructs are permitted in constant expressions:

  • 리터럴 (null 리터럴 포함)Literals (including the null literal).
  • 클래스 및 구조체 형식의 const 멤버에 대 한 참조입니다.References to const members of class and struct types.
  • 열거형 형식의 멤버에 대 한 참조입니다.References to members of enumeration types.
  • 0 @no__t 매개 변수 또는 지역 변수에 대 한 참조References to const parameters or local variables
  • 괄호로 묶은 하위 식으로, 상수 식입니다.Parenthesized sub-expressions, which are themselves constant expressions.
  • Cast 식은 대상 형식이 위에 나열 된 형식 중 하나입니다.Cast expressions, provided the target type is one of the types listed above.
  • checkeduncheckedchecked and unchecked expressions
  • 기본값 식Default value expressions
  • 식의 nameNameof expressions
  • 미리 정의 된 +, -, !~ 단항 연산자입니다.The predefined +, -, !, and ~ unary operators.
  • 미리 정의 된 +, 각 피연산자가 인 경우 -, @no__t, /, %, @no__t, >>, &, | ^, 0, 1, 2, 3, 4, 5, 6, 7 이항 연산자 위에 나열 된 유형입니다.The predefined +, -, *, /, %, <<, >>, &, |, ^, &&, ||, ==, !=, <, >, <=, and >= binary operators, provided each operand is of a type listed above.
  • @No__t-0 조건부 연산자입니다.The ?: conditional operator.

상수 식에는 다음과 같은 변환이 허용 됩니다.The following conversions are permitted in constant expressions:

  • Id 변환Identity conversions
  • 숫자 변환Numeric conversions
  • 열거형 변환Enumeration conversions
  • 상수 식 변환Constant expression conversions
  • 암시적 및 명시적 참조 변환. 변환의 소스는 null 값으로 계산 되는 상수 식일 수 있습니다.Implicit and explicit reference conversions, provided that the source of the conversions is a constant expression that evaluates to the null value.

Null이 아닌 값의 boxing, unboxing 및 암시적 참조 변환을 비롯 한 다른 변환은 상수 식에서 허용 되지 않습니다.Other conversions including boxing, unboxing and implicit reference conversions of non-null values are not permitted in constant expressions. 예를 들어 다음과 같은 가치를 제공해야 합니다.For example:

class C {
    const object i = 5;         // error: boxing conversion not permitted
    const object str = "hello"; // error: implicit reference conversion
}

boxing 변환이 필요 하므로 i를 초기화 하는 것은 오류입니다.the initialization of i is an error because a boxing conversion is required. Null이 아닌 값에서 암시적 참조가 필요 하므로 str를 초기화 하는 것은 오류입니다.The initialization of str is an error because an implicit reference conversion from a non-null value is required.

식이 위에 나열 된 요구 사항을 충족 하는 경우 식은 컴파일 시간에 계산 됩니다.Whenever an expression fulfills the requirements listed above, the expression is evaluated at compile-time. 식이 비상수 구문을 포함 하는 더 큰 식의 하위 식인 경우에도 마찬가지입니다.This is true even if the expression is a sub-expression of a larger expression that contains non-constant constructs.

상수 식의 컴파일 타임 계산은 런타임 계산이 예외를 throw 하는 경우를 제외 하 고 비상수 식의 런타임 평가와 동일한 규칙을 사용 합니다. 단, 컴파일 타임 계산으로 인해 컴파일 시간 오류가 발생 합니다.The compile-time evaluation of constant expressions uses the same rules as run-time evaluation of non-constant expressions, except that where run-time evaluation would have thrown an exception, compile-time evaluation causes a compile-time error to occur.

상수 식이 unchecked 컨텍스트에 명시적으로 배치 되어 있지 않으면 식의 컴파일 타임 계산 중에 정수 계열 형식 산술 연산에서 발생 하는 오버플로는 항상 컴파일 시간 오류 (상수)를 발생 시킵니다.).Unless a constant expression is explicitly placed in an unchecked context, overflows that occur in integral-type arithmetic operations and conversions during the compile-time evaluation of the expression always cause compile-time errors (Constant expressions).

상수 식은 아래 나열 된 컨텍스트에서 발생 합니다.Constant expressions occur in the contexts listed below. 이러한 컨텍스트에서는 컴파일 시간에 식을 완전히 계산할 수 없는 경우 컴파일 타임 오류가 발생 합니다.In these contexts, a compile-time error occurs if an expression cannot be fully evaluated at compile-time.

암시적 상수 식 변환 (암시적 상수식 변환)을 사용 하면 int 형식의 상수 식이 sbyte, byte, short, uint, ulong로 변환 되어 값이 제공 됩니다. 상수 식이 대상 형식의 범위 내에 있습니다.An implicit constant expression conversion (Implicit constant expression conversions) permits a constant expression of type int to be converted to sbyte, byte, short, ushort, uint, or ulong, provided the value of the constant expression is within the range of the destination type.

부울 식Boolean expressions

Boolean_expression 는 @no__t 형식의 결과를 생성 하는 식입니다. 직접 또는 다음에 지정 된 특정 컨텍스트에서 operator true의 응용 프로그램을 통해 수행 합니다.A boolean_expression is an expression that yields a result of type bool; either directly or through application of operator true in certain contexts as specified in the following.

boolean_expression
    : expression
    ;

If_statement (if 문), while_statement (while 문), do_statement (do 문) 또는 for_statement (의 경우)의 제어 조건 식 statement)는 boolean_expression입니다.The controlling conditional expression of an if_statement (The if statement), while_statement (The while statement), do_statement (The do statement), or for_statement (The for statement) is a boolean_expression. @No__t-0 연산자 (조건부 연산자)의 제어 조건 식은 boolean_expression와 동일한 규칙을 따르며 연산자 우선 순위는 conditional_or_expression로 분류 됩니다.The controlling conditional expression of the ?: operator (Conditional operator) follows the same rules as a boolean_expression, but for reasons of operator precedence is classified as a conditional_or_expression.

Boolean_expression E은 다음과 같이 bool 형식의 값을 생성 하는 데 필요 합니다.A boolean_expression E is required to be able to produce a value of type bool, as follows:

  • @No__t-0이 bool로 암시적으로 변환할 수 있으면 런타임 시 암시적 변환이 적용 됩니다.If E is implicitly convertible to bool then at runtime that implicit conversion is applied.
  • 그렇지 않으면 단항 연산자 오버 로드 확인 (단항 연산자 오버 로드 확인)을 사용 하 여 E에서 true의 가장 고유한 최적 구현을 찾고 해당 구현이 런타임에 적용 됩니다.Otherwise, unary operator overload resolution (