
- •Language Specification
- •Version 4.0
- •1. Introduction 1
- •2. Lexical structure 37
- •3. Basic concepts 59
- •4. Types 83
- •5. Variables 99
- •6. Conversions 115
- •7. Expressions 137
- •8. Statements 239
- •9. Namespaces 268
- •10. Classes 279
- •11. Structs 376
- •12. Arrays 389
- •12.1 Array types 389
- •13. Interfaces 395
- •18. Unsafe code 443
- •1.Introduction
- •1.1Hello world
- •1.2Program structure
- •1.3Types and variables
- •1.4Expressions
- •1.5Statements
- •1.6Classes and objects
- •1.6.1Members
- •1.6.2Accessibility
- •1.6.3Type parameters
- •1.6.4Base classes
- •1.6.5Fields
- •1.6.6Methods
- •1.6.6.1Parameters
- •1.6.6.2Method body and local variables
- •1.6.6.3Static and instance methods
- •1.6.6.4Virtual, override, and abstract methods
- •1.6.6.5Method overloading
- •1.6.7Other function members
- •1.6.7.1Constructors
- •1.6.7.2Properties
- •1.6.7.3Indexers
- •1.6.7.4Events
- •1.6.7.5Operators
- •1.6.7.6Destructors
- •1.7Structs
- •1.8Arrays
- •1.9Interfaces
- •1.10Enums
- •1.11Delegates
- •1.12Attributes
- •2.Lexical structure
- •2.1Programs
- •2.2Grammars
- •2.2.1Grammar notation
- •2.2.2Lexical grammar
- •2.2.3Syntactic grammar
- •2.3Lexical analysis
- •2.3.1Line terminators
- •2.3.2Comments
- •2.3.3White space
- •2.4Tokens
- •2.4.1Unicode character escape sequences
- •2.4.2Identifiers
- •2.4.3Keywords
- •2.4.4Literals
- •2.4.4.1Boolean literals
- •2.4.4.2Integer literals
- •2.4.4.3Real literals
- •2.4.4.4Character literals
- •2.4.4.5String literals
- •2.4.4.6The null literal
- •2.4.5Operators and punctuators
- •2.5Pre-processing directives
- •2.5.1Conditional compilation symbols
- •2.5.2Pre-processing expressions
- •2.5.3Declaration directives
- •2.5.4Conditional compilation directives
- •2.5.5Diagnostic directives
- •2.5.6Region directives
- •2.5.7Line directives
- •2.5.8Pragma directives
- •2.5.8.1Pragma warning
- •3.Basic concepts
- •3.1Application Startup
- •3.2Application termination
- •3.3Declarations
- •3.4Members
- •3.4.1Namespace members
- •3.4.2Struct members
- •3.4.3Enumeration members
- •3.4.4Class members
- •3.5.1Declared accessibility
- •3.5.2Accessibility domains
- •3.5.3Protected access for instance members
- •3.5.4Accessibility constraints
- •3.6Signatures and overloading
- •3.7Scopes
- •3.7.1Name hiding
- •3.7.1.1Hiding through nesting
- •3.7.1.2Hiding through inheritance
- •3.8Namespace and type names
- •3.8.1Fully qualified names
- •3.9Automatic memory management
- •3.10Execution order
- •4.Types
- •4.1Value types
- •4.1.1The System.ValueType type
- •4.1.2Default constructors
- •4.1.3Struct types
- •4.1.4Simple types
- •4.1.5Integral types
- •4.1.6Floating point types
- •4.1.7The decimal type
- •4.1.8The bool type
- •4.1.9Enumeration types
- •4.1.10Nullable types
- •4.2Reference types
- •4.2.1Class types
- •4.2.2The object type
- •4.2.3The dynamic type
- •4.3Boxing and unboxing
- •4.3.1Boxing conversions
- •4.3.2Unboxing conversions
- •4.4Constructed types
- •4.4.1Type arguments
- •4.4.2Open and closed types
- •4.4.3Bound and unbound types
- •4.4.4Satisfying constraints
- •4.5Type parameters
- •4.6Expression tree types
- •4.7The dynamic type
- •5.Variables
- •5.1Variable categories
- •5.1.1Static variables
- •5.1.2Instance variables
- •5.1.2.1Instance variables in classes
- •5.1.2.2Instance variables in structs
- •5.1.3Array elements
- •5.1.4Value parameters
- •5.1.5Reference parameters
- •5.1.6Output parameters
- •5.1.7Local variables
- •5.2Default values
- •5.3Definite assignment
- •5.3.1Initially assigned variables
- •Value parameters.
- •5.3.2Initially unassigned variables
- •5.3.3Precise rules for determining definite assignment
- •5.3.3.1General rules for statements
- •5.3.3.2Block statements, checked, and unchecked statements
- •5.3.3.3Expression statements
- •5.3.3.4Declaration statements
- •5.3.3.5If statements
- •5.3.3.6Switch statements
- •5.3.3.7While statements
- •5.3.3.8Do statements
- •5.3.3.9For statements
- •5.3.3.10Break, continue, and goto statements
- •5.3.3.11Throw statements
- •5.3.3.12Return statements
- •5.3.3.13Try-catch statements
- •5.3.3.14Try-finally statements
- •5.3.3.15Try-catch-finally statements
- •5.3.3.21General rules for expressions with embedded expressions
- •5.3.3.22Invocation expressions and object creation expressions
- •5.3.3.23Simple assignment expressions
- •5.3.3.24&& Expressions
- •5.3.3.25|| Expressions
- •5.3.3.26! Expressions
- •5.3.3.27?? Expressions
- •5.3.3.28?: Expressions
- •5.3.3.29Anonymous functions
- •5.4Variable references
- •5.5Atomicity of variable references
- •6.Conversions
- •6.1Implicit conversions
- •6.1.1Identity conversion
- •6.1.2Implicit numeric conversions
- •6.1.3Implicit enumeration conversions
- •6.1.4Implicit nullable conversions
- •6.1.5Null literal conversions
- •6.1.6Implicit reference conversions
- •6.1.7Boxing conversions
- •6.1.8Implicit dynamic conversions
- •6.1.9Implicit constant expression conversions
- •6.1.10Implicit conversions involving type parameters
- •6.1.11User-defined implicit conversions
- •6.1.12Anonymous function conversions and method group conversions
- •6.2Explicit conversions
- •6.2.1Explicit numeric conversions
- •6.2.2Explicit enumeration conversions
- •6.2.3Explicit nullable conversions
- •6.2.4Explicit reference conversions
- •6.2.5Unboxing conversions
- •6.2.6Explicit dynamic conversions
- •6.2.7Explicit conversions involving type parameters
- •6.2.8User-defined explicit conversions
- •6.3Standard conversions
- •6.3.1Standard implicit conversions
- •6.3.2Standard explicit conversions
- •6.4User-defined conversions
- •6.4.1Permitted user-defined conversions
- •6.4.2Lifted conversion operators
- •6.4.3Evaluation of user-defined conversions
- •6.4.4User-defined implicit conversions
- •6.4.5User-defined explicit conversions
- •6.5Anonymous function conversions
- •6.5.1Evaluation of anonymous function conversions to delegate types
- •6.5.2Evaluation of anonymous function conversions to expression tree types
- •6.5.3Implementation example
- •6.6Method group conversions
- •7.Expressions
- •7.1Expression classifications
- •7.1.1Values of expressions
- •7.2Static and Dynamic Binding
- •7.2.1Binding-time
- •7.2.2Dynamic binding
- •7.2.3Types of constituent expressions
- •7.3Operators
- •7.3.1Operator precedence and associativity
- •7.3.2Operator overloading
- •7.3.3Unary operator overload resolution
- •7.3.4Binary operator overload resolution
- •7.3.5Candidate user-defined operators
- •7.3.6Numeric promotions
- •7.3.6.1Unary numeric promotions
- •7.3.6.2Binary numeric promotions
- •7.3.7Lifted operators
- •7.4Member lookup
- •7.4.1Base types
- •7.5Function members
- •Indexers
- •Instance constructors
- •7.5.1Argument lists
- •7.5.1.1Corresponding parameters
- •7.5.1.2Run-time evaluation of argument lists
- •7.5.2Type inference
- •7.5.2.1The first phase
- •7.5.2.2The second phase
- •7.5.2.7Explicit parameter type inferences
- •7.5.2.8Exact inferences
- •7.5.2.9Lower-bound inferences
- •7.5.2.10Upper-bound inferences
- •7.5.2.11Fixing
- •7.5.2.12Inferred return type
- •7.5.2.13Type inference for conversion of method groups
- •7.5.2.14Finding the best common type of a set of expressions
- •7.5.3Overload resolution
- •7.5.3.1Applicable function member
- •7.5.3.2Better function member
- •7.5.3.3Better conversion from expression
- •7.5.3.4Better conversion from type
- •7.5.3.5Better conversion target
- •7.5.3.6Overloading in generic classes
- •7.5.4Compile-time checking of dynamic overload resolution
- •7.5.5Function member invocation
- •7.5.5.1Invocations on boxed instances
- •7.6Primary expressions
- •7.6.1Literals
- •7.6.2Simple names
- •7.6.2.1Invariant meaning in blocks
- •7.6.3Parenthesized expressions
- •7.6.4Member access
- •7.6.4.1Identical simple names and type names
- •7.6.4.2Grammar ambiguities
- •7.6.5Invocation expressions
- •7.6.5.1Method invocations
- •7.6.5.2Extension method invocations
- •7.6.5.3Delegate invocations
- •7.6.6Element access
- •7.6.6.1Array access
- •7.6.6.2Indexer access
- •7.6.7This access
- •7.6.8Base access
- •7.6.9Postfix increment and decrement operators
- •7.6.10The new operator
- •7.6.10.1Object creation expressions
- •7.6.10.2Object initializers
- •7.6.10.3Collection initializers
- •7.6.10.4Array creation expressions
- •7.6.10.5Delegate creation expressions
- •7.6.10.6Anonymous object creation expressions
- •7.6.11The typeof operator
- •7.6.12The checked and unchecked operators
- •7.6.13Default value expressions
- •7.6.14Anonymous method expressions
- •7.7Unary operators
- •7.7.1Unary plus operator
- •7.7.2Unary minus operator
- •7.7.3Logical negation operator
- •7.7.4Bitwise complement operator
- •7.7.5Prefix increment and decrement operators
- •7.7.6Cast expressions
- •7.8Arithmetic operators
- •7.8.1Multiplication operator
- •7.8.2Division operator
- •7.8.3Remainder operator
- •7.8.4Addition operator
- •7.8.5Subtraction operator
- •7.9Shift operators
- •7.10Relational and type-testing operators
- •7.10.1Integer comparison operators
- •7.10.2Floating-point comparison operators
- •7.10.3Decimal comparison operators
- •7.10.4Boolean equality operators
- •7.10.5Enumeration comparison operators
- •7.10.6Reference type equality operators
- •7.10.7String equality operators
- •7.10.8Delegate equality operators
- •7.10.9Equality operators and null
- •7.10.10The is operator
- •7.10.11The as operator
- •7.11Logical operators
- •7.11.1Integer logical operators
- •7.11.2Enumeration logical operators
- •7.11.3Boolean logical operators
- •7.11.4Nullable boolean logical operators
- •7.12Conditional logical operators
- •7.12.1Boolean conditional logical operators
- •7.12.2User-defined conditional logical operators
- •7.13The null coalescing operator
- •7.14Conditional operator
- •7.15Anonymous function expressions
- •7.15.1Anonymous function signatures
- •7.15.2Anonymous function bodies
- •7.15.3Overload resolution
- •7.15.4Anonymous functions and dynamic binding
- •7.15.5Outer variables
- •7.15.5.1Captured outer variables
- •7.15.5.2Instantiation of local variables
- •7.15.6Evaluation of anonymous function expressions
- •7.16Query expressions
- •7.16.1Ambiguities in query expressions
- •7.16.2Query expression translation
- •7.16.2.1Select and groupby clauses with continuations
- •7.16.2.2Explicit range variable types
- •7.16.2.3Degenerate query expressions
- •7.16.2.4From, let, where, join and orderby clauses
- •7.16.2.5Select clauses
- •7.16.2.6Groupby clauses
- •7.16.2.7Transparent identifiers
- •7.16.3The query expression pattern
- •7.17Assignment operators
- •7.17.1Simple assignment
- •7.17.2Compound assignment
- •7.17.3Event assignment
- •7.18Expression
- •7.19Constant expressions
- •7.20Boolean expressions
- •8.Statements
- •8.1End points and reachability
- •8.2Blocks
- •8.2.1Statement lists
- •8.3The empty statement
- •8.4Labeled statements
- •8.5Declaration statements
- •8.5.1Local variable declarations
- •8.5.2Local constant declarations
- •8.6Expression statements
- •8.7Selection statements
- •8.7.1The if statement
- •8.7.2The switch statement
- •8.8Iteration statements
- •8.8.1The while statement
- •8.8.2The do statement
- •8.8.3The for statement
- •8.8.4The foreach statement
- •8.9Jump statements
- •8.9.1The break statement
- •8.9.2The continue statement
- •8.9.3The goto statement
- •8.9.4The return statement
- •8.9.5The throw statement
- •8.10The try statement
- •8.11The checked and unchecked statements
- •8.12The lock statement
- •8.13The using statement
- •8.14The yield statement
- •9.Namespaces
- •9.1Compilation units
- •9.2Namespace declarations
- •9.3Extern aliases
- •9.4Using directives
- •9.4.1Using alias directives
- •9.4.2Using namespace directives
- •9.5Namespace members
- •9.6Type declarations
- •9.7Namespace alias qualifiers
- •9.7.1Uniqueness of aliases
- •10.Classes
- •10.1Class declarations
- •10.1.1Class modifiers
- •10.1.1.1Abstract classes
- •10.1.1.2Sealed classes
- •10.1.1.3Static classes
- •10.1.1.3.1Referencing static class types
- •10.1.2Partial modifier
- •10.1.3Type parameters
- •10.1.4Class base specification
- •10.1.4.1Base classes
- •10.1.4.2Interface implementations
- •10.1.5Type parameter constraints
- •10.1.6Class body
- •10.2Partial types
- •10.2.1Attributes
- •10.2.2Modifiers
- •10.2.3Type parameters and constraints
- •10.2.4Base class
- •10.2.5Base interfaces
- •10.2.6Members
- •10.2.7Partial methods
- •10.2.8Name binding
- •10.3Class members
- •10.3.1The instance type
- •10.3.2Members of constructed types
- •10.3.3Inheritance
- •10.3.4The new modifier
- •10.3.5Access modifiers
- •10.3.6Constituent types
- •10.3.7Static and instance members
- •10.3.8Nested types
- •10.3.8.1Fully qualified name
- •10.3.8.2Declared accessibility
- •10.3.8.3Hiding
- •10.3.8.4This access
- •10.3.8.5Access to private and protected members of the containing type
- •10.3.8.6Nested types in generic classes
- •10.3.9Reserved member names
- •10.3.9.1Member names reserved for properties
- •10.5Fields
- •10.5.1Static and instance fields
- •10.5.2Readonly fields
- •10.5.2.1Using static readonly fields for constants
- •10.5.2.2Versioning of constants and static readonly fields
- •10.5.3Volatile fields
- •10.5.4Field initialization
- •10.5.5Variable initializers
- •10.5.5.1Static field initialization
- •10.5.5.2Instance field initialization
- •10.6Methods
- •10.6.1Method parameters
- •10.6.1.1Value parameters
- •10.6.1.2Reference parameters
- •10.6.1.3Output parameters
- •10.6.1.4Parameter arrays
- •10.6.2Static and instance methods
- •10.6.3Virtual methods
- •10.6.4Override methods
- •10.6.5Sealed methods
- •10.6.6Abstract methods
- •10.6.7External methods
- •10.6.8Partial methods
- •10.6.9Extension methods
- •10.6.10Method body
- •10.6.11Method overloading
- •10.7Properties
- •10.7.1Static and instance properties
- •10.7.2Accessors
- •10.7.3Automatically implemented properties
- •10.7.4Accessibility
- •10.7.5Virtual, sealed, override, and abstract accessors
- •10.8Events
- •10.8.1Field-like events
- •10.8.2Event accessors
- •10.8.3Static and instance events
- •10.8.4Virtual, sealed, override, and abstract accessors
- •10.9Indexers
- •10.9.1Indexer overloading
- •10.10Operators
- •10.10.1Unary operators
- •10.10.2Binary operators
- •10.10.3Conversion operators
- •10.11Instance constructors
- •10.11.1Constructor initializers
- •10.11.2Instance variable initializers
- •10.11.3Constructor execution
- •10.11.4Default constructors
- •10.11.5Private constructors
- •10.11.6Optional instance constructor parameters
- •10.12Static constructors
- •10.13Destructors
- •10.14Iterators
- •10.14.4.1The MoveNext method
- •10.14.4.2The Current property
- •10.14.4.3The Dispose method
- •10.14.5Enumerable objects
- •10.14.5.1The GetEnumerator method
- •10.14.6Implementation example
- •11.Structs
- •11.1Struct declarations
- •11.1.1Struct modifiers
- •11.3Class and struct differences
- •11.3.1Value semantics
- •11.3.2Inheritance
- •11.3.3Assignment
- •11.3.4Default values
- •11.3.5Boxing and unboxing
- •11.3.6Meaning of this
- •11.3.7Field initializers
- •11.3.8Constructors
- •11.3.9Destructors
- •11.3.10Static constructors
- •11.4Struct examples
- •11.4.1Database integer type
- •11.4.2Database boolean type
- •12.Arrays
- •12.1Array types
- •12.1.1The System.Array type
- •12.1.2Arrays and the generic iList interface
- •12.2Array creation
- •12.3Array element access
- •12.4Array members
- •12.5Array covariance
- •12.6Array initializers
- •13.Interfaces
- •13.1Interface declarations
- •13.1.1Interface modifiers
- •13.1.2Partial modifier
- •13.1.3Variant type parameter lists
- •13.1.3.1Variance safety
- •13.1.3.2Variance conversion
- •13.1.4Base interfaces
- •13.1.5Interface body
- •13.2Interface members
- •13.2.1Interface methods
- •13.2.2Interface properties
- •13.2.3Interface events
- •13.2.4Interface indexers
- •13.2.5Interface member access
- •13.3Fully qualified interface member names
- •13.4Interface implementations
- •13.4.1Explicit interface member implementations
- •13.4.2Uniqueness of implemented interfaces
- •13.4.3Implementation of generic methods
- •13.4.4Interface mapping
- •13.4.5Interface implementation inheritance
- •13.4.6Interface re-implementation
- •13.4.7Abstract classes and interfaces
- •14.Enums
- •14.1Enum declarations
- •14.2Enum modifiers
- •14.3Enum members
- •14.4The System.Enum type
- •14.5Enum values and operations
- •15.Delegates
- •15.1Delegate declarations
- •15.2Delegate compatibility
- •15.3Delegate instantiation
- •15.4Delegate invocation
- •16.Exceptions
- •16.1Causes of exceptions
- •16.2The System.Exception class
- •16.3How exceptions are handled
- •16.4Common Exception Classes
- •17.Attributes
- •17.1Attribute classes
- •17.1.1Attribute usage
- •17.1.2Positional and named parameters
- •17.1.3Attribute parameter types
- •17.2Attribute specification
- •17.3Attribute instances
- •17.3.1Compilation of an attribute
- •17.3.2Run-time retrieval of an attribute instance
- •17.4Reserved attributes
- •17.4.1The AttributeUsage attribute
- •17.4.2The Conditional attribute
- •17.4.2.1Conditional methods
- •17.4.2.2Conditional attribute classes
- •17.4.3The Obsolete attribute
- •17.5Attributes for Interoperation
- •17.5.1Interoperation with com and Win32 components
- •17.5.2Interoperation with other .Net languages
- •17.5.2.1The IndexerName attribute
- •18.Unsafe code
- •18.1Unsafe contexts
- •18.2Pointer types
- •18.3Fixed and moveable variables
- •18.4Pointer conversions
- •18.4.1Pointer arrays
- •18.5Pointers in expressions
- •18.5.1Pointer indirection
- •18.5.2Pointer member access
- •18.5.3Pointer element access
- •18.5.4The address-of operator
- •18.5.5Pointer increment and decrement
- •18.5.6Pointer arithmetic
- •18.5.7Pointer comparison
- •18.5.8The sizeof operator
- •18.6The fixed statement
- •18.7Fixed size buffers
- •18.7.1Fixed size buffer declarations
- •18.7.2Fixed size buffers in expressions
- •18.7.3Definite assignment checking
- •18.8Stack allocation
- •18.9Dynamic memory allocation
- •Documentation comments
- •Introduction
- •Recommended tags
- •Processing the documentation file
- •Id string format
- •Id string examples
- •An example
- •C# source code
- •Resulting xml
- •Keywords
- •Literals
- •Operators and punctuators
- •Syntactic grammar
- •Basic concepts
- •Variables
- •Expressions
- •Statements
- •Namespaces
- •Classes
- •Structs
- •Interfaces
- •Delegates
- •Attributes
- •Grammar extensions for unsafe code
- •References
- •Copyright ó Microsoft Corporation 1999-20101998. All Rights Reserved. Please send corrections, comments, and other feedback to csharp@microsoft.Com
7.6.4.1Identical simple names and type names
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 (§7.6.2) is a constant, field, property, local variable, or parameter with the same type as the meaning of E as a type-name (§3.8), then both possible meanings of E are permitted. The two possible meanings of E.I are never ambiguous, since I must necessarily be a member of the type E in both cases. 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 } }
Within the A class, those occurrences of the Color identifier that reference the Color type are underlined, and those that reference the Color field are not underlined.
7.6.4.2Grammar ambiguities
The productions for simple-name (§7.6.2) and member-access (§7.6.4) can give rise to ambiguities in the grammar for expressions. For example, the statement:
F(G<A,B>(7));
could be interpreted as a call to F with two arguments, G < A and B > (7). 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.
If a sequence of tokens can be parsed (in context) as a simple-name (§7.6.2), member-access (§7.6.4), or pointer-member-access (§18.5.2) ending with a type-argument-list (§4.4.1), the token immediately following the closing > token is examined. If it is one of
( ) ] } : ; , . ? == != | ^
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. 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. Note that these rules are not applied when parsing a type-argument-list in a namespace-or-type-name (§3.8). The statement
F(G<A,B>(7));
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);
will each be interpreted as a call to F with two arguments. The statement
x = F < A > +y;
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;
the tokens C<T> are interpreted as a namespace-or-type-name with a type-argument-list.