Member access
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: predefined-type: one of The qualified-alias-member production is defined in §9.7. 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. When no type-argument-list is specified, consider K to be zero. A member-access with a primary-expression of type dynamic is dynamically bound (§7.2.2). In this case the compiler classifies the member access as a property access of type dynamic. 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. If this run-time classification leads to a method group, then the member access must be the primary-expression of an invocation-expression. The member-access is evaluated and classified as follows: · If K is zero and E is a namespace and E contains a nested namespace with name I, then the result is that namespace. · 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. · 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 (§7.4) of I in E with K type parameters produces a match, then E.I is evaluated and classified as follows: o If I identifies a type, then the result is that type constructed with the given type arguments. o 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 (§7.6.5.1). o If I identifies a static property, then the result is a property access with no associated instance expression. o If I identifies a static field: · 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. · Otherwise, the result is a variable, namely the static field I in E. o If I identifies a static event: · If the reference occurs within the class or struct in which the event is declared, and the event was declared without event-accessor-declarations (§10.8), 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. o If I identifies a constant, then the result is a value, namely the value of that constant. o If I identifies an enumeration member, then the result is a value, namely the value of that enumeration member. o Otherwise, E.I is an invalid member reference, and a compile-time error occurs. · If E is a property access, indexer access, variable, or value, the type of which is T, and a member lookup (§7.4) of I in T with K type arguments produces a match, then E.I is evaluated and classified as follows: o First, if E is a property or indexer access, then the value of the property or indexer access is obtained (§7.1.1) and E is reclassified as a value. o 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 (§7.6.5.1). o If I identifies an instance property, then the result is a property access with an associated instance expression of E. o If T is a class-type and I identifies an instance field of that class-type: · If the value of E is null, then a System.NullReferenceException is thrown. · 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. · Otherwise, the result is a variable, namely the field I in the object referenced by E. o If T is a struct-type and I identifies an instance field of that struct-type: · 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. · Otherwise, the result is a variable, namely the field I in the struct instance given by E. o If I identifies an instance event: · If the reference occurs within the class or struct in which the event is declared, and the event was declared without event-accessor-declarations (§10.8), 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. · Otherwise, the result is an event access with an associated instance expression of E. · Otherwise, an attempt is made to process E.I as an extension method invocation (§7.6.5.2). If this fails, E.I is an invalid member reference, and a binding-time error occurs.
|