c# language specification - ecma international shar…  · web viewin fact the second string...

869
C # Language Specification Working Draft WD3.14 November 16 2016

Upload: tranthuan

Post on 30-Jan-2018

216 views

Category:

Documents


0 download

TRANSCRIPT

C# Language Specification

C#

Language Specification

Working Draft WD3.14

November 16 2016

Table of Contents

Forewordxix

Introductionxx

1. Scope1

2. Conformance3

3. Normative references5

4. Terms and definitions7

5. Acronyms and abbreviations13

6. General description15

7. Language overview17

8. Lexical structure51

8.1 Programs51

8.2 Grammars51

8.2.1 General51

8.2.2 Grammar notation51

8.2.3 Lexical grammar53

8.2.4 Syntactic grammar54

8.2.5 Grammar ambiguities54

8.3 Lexical analysis55

8.3.1 General55

8.3.2 Line terminators55

8.3.3 Comments56

8.3.4 White space57

8.4 Tokens58

8.4.1 General58

8.4.2 Unicode character escape sequences58

8.4.3 Identifiers59

8.4.4 Keywords60

8.4.5 Literals62

8.4.5.1 General62

8.4.5.2 Boolean literals62

8.4.5.3 Integer literals62

8.4.5.4 Real literals63

8.4.5.5 Character literals64

8.4.5.6 String literals65

8.4.5.7 The null literal67

8.4.6 Operators and punctuators67

8.5 Pre-processing directives67

8.5.1 General67

8.5.2 Conditional compilation symbols69

8.5.3 Pre-processing expressions69

8.5.4 Definition directives70

8.5.5 Conditional compilation directives71

8.5.6 Diagnostic directives73

8.5.7 Region directives74

8.5.8 Line directives74

8.5.9 Pragma directives75

8.5.9.1 General75

8.5.9.2 Pragma warning76

9. Basic concepts77

9.1 Application startup77

9.2 Application termination79

9.3 Declarations79

9.4 Members84

9.4.1 General84

9.4.2 Namespace members84

9.4.3 Struct members84

9.4.4 Enumeration members85

9.4.5 Class members85

9.4.6 Interface members85

9.4.7 Array members85

9.4.8 Delegate members85

9.5 Member access85

9.5.1 General85

9.5.2 Declared accessibility86

9.5.3 Accessibility domains86

9.5.4 Protected access for instance members89

9.5.5 Accessibility constraints90

9.6 Signatures and overloading91

9.7 Scopes92

9.7.1 General92

9.7.2 Name hiding95

9.7.2.1 General95

9.7.2.2 Hiding through nesting95

9.7.2.3 Hiding through inheritance96

9.8 Namespace and type names97

9.8.1 General97

9.8.2 Fully qualified names99

9.9 Automatic memory management100

9.10 Execution order103

10. Types105

10.1 General105

10.2 Value types105

10.2.1 General105

10.2.2 The System.ValueType type106

10.2.3 Default constructors106

10.2.4 Struct types107

10.2.5 Simple types107

10.2.6 Integral types108

10.2.7 Floating-point types109

10.2.8 The decimal type111

10.2.9 The bool type111

10.2.10 Enumeration types112

10.2.11 Nullable value types112

10.3 Reference types112

10.3.1 General112

10.3.2 Class types113

10.3.3 The object type114

10.3.4 The dynamic type114

10.3.5 The string type114

10.3.6 Interface types114

10.3.7 Array types114

10.3.8 Delegate types114

10.4 Boxing and unboxing115

10.4.1 General115

10.4.2 Boxing conversions115

10.4.3 Unboxing conversions117

10.5 Constructed types119

10.5.1 General119

10.5.2 Type arguments119

10.5.3 Open and closed types120

10.5.4 Bound and unbound types120

10.5.5 Satisfying constraints120

10.6 Type parameters121

10.7 Expression tree types122

10.8 The dynamic type123

11. Variables125

11.1 General125

11.2 Variable categories125

11.2.1 General125

11.2.2 Static variables125

11.2.3 Instance variables125

11.2.3.1 General125

11.2.3.2 Instance variables in classes126

11.2.3.3 Instance variables in structs126

11.2.4 Array elements126

11.2.5 Value parameters126

11.2.6 Reference parameters126

11.2.7 Output parameters127

11.2.8 Local variables127

11.3 Default values128

11.4 Definite assignment128

11.4.1 General128

11.4.2 Initially assigned variables129

11.4.3 Initially unassigned variables129

11.4.4 Precise rules for determining definite assignment130

11.4.4.1 General130

11.4.4.2 General rules for statements130

11.4.4.3 Block statements, checked, and unchecked statements130

11.4.4.4 Expression statements131

11.4.4.5 Declaration statements131

11.4.4.6 If statements131

11.4.4.7 Switch statements131

11.4.4.8 While statements131

11.4.4.9 Do statements132

11.4.4.10 For statements132

11.4.4.11 Break, continue, and goto statements132

11.4.4.12 Throw statements132

11.4.4.13 Return statements132

11.4.4.14 Try-catch statements133

11.4.4.15 Try-finally statements133

11.4.4.16 Try-catch-finally statements133

11.4.4.17 Foreach statements134

11.4.4.18 Using statements134

11.4.4.19 Lock statements135

11.4.4.20 Yield statements135

11.4.4.21 General rules for constant expressions135

11.4.4.22 General rules for simple expressions136

11.4.4.23 General rules for expressions with embedded expressions136

11.4.4.24 Invocation expressions and object creation expressions136

11.4.4.25 Simple assignment expressions137

11.4.4.26 && expressions137

11.4.4.27 || expressions138

11.4.4.28 ! expressions139

11.4.4.29 ?? expressions139

11.4.4.30 ?: expressions140

11.4.4.31 Anonymous functions140

11.5 Variable references142

11.6 Atomicity of variable references142

12. Conversions143

12.1 General143

12.2 Implicit conversions143

12.2.1 General143

12.2.2 Identity conversion144

12.2.3 Implicit numeric conversions144

12.2.4 Implicit enumeration conversions144

12.2.5 Implicit nullable conversions144

12.2.6 Null literal conversions145

12.2.7 Implicit reference conversions145

12.2.8 Boxing conversions146

12.2.9 Implicit dynamic conversions147

12.2.10 Implicit constant expression conversions147

12.2.11 Implicit conversions involving type parameters147

12.2.12 User-defined implicit conversions148

12.2.13 Anonymous function conversions and method group conversions148

12.3 Explicit conversions148

12.3.1 General148

12.3.2 Explicit numeric conversions149

12.3.3 Explicit enumeration conversions151

12.3.4 Explicit nullable conversions151

12.3.5 Explicit reference conversions151

12.3.6 Unboxing conversions152

12.3.7 Explicit dynamic conversions153

12.3.8 Explicit conversions involving type parameters154

12.3.9 User-defined explicit conversions155

12.4 Standard conversions155

12.4.1 General155

12.4.2 Standard implicit conversions155

12.4.3 Standard explicit conversions155

12.5 User-defined conversions155

12.5.1 General155

12.5.2 Permitted user-defined conversions156

12.5.3 Lifted conversion operators156

12.5.4 Evaluation of user-defined conversions156

12.5.5 User-defined implicit conversions157

12.5.6 User-defined explicit conversions158

12.6 Conversions involving nullable types160

12.6.1 Nullable Conversions160

12.6.2 Lifted conversions160

12.7 Anonymous function conversions160

12.7.1 General160

12.7.2 Evaluation of anonymous function conversions to delegate types162

12.7.3 Evaluation of anonymous function conversions to expression tree types163

12.7.4 Implementation example163

12.8 Method group conversions167

13. Expressions170

13.1 General170

13.2 Expression classifications170

13.2.1 General170

13.2.2 Values of expressions171

13.3 Static and Dynamic Binding171

13.3.1 General171

13.3.2 Binding-time172

13.3.3 Dynamic binding172

13.3.4 Types of subexpressions173

13.4 Operators173

13.4.1 General173

13.4.2 Operator precedence and associativity173

13.4.3 Operator overloading174

13.4.4 Unary operator overload resolution176

13.4.5 Binary operator overload resolution176

13.4.6 Candidate user-defined operators177

13.4.7 Numeric promotions177

13.4.7.1 General177

13.4.7.2 Unary numeric promotions177

13.4.7.3 Binary numeric promotions178

13.4.8 Lifted operators178

13.5 Member lookup179

13.5.1 General179

13.5.2 Base types180

13.6 Function members181

13.6.1 General181

13.6.2 Argument lists183

13.6.2.1 General183

13.6.2.2 Corresponding parameters185

13.6.2.3 Run-time evaluation of argument lists185

13.6.3 Type inference187

13.6.3.1 General187

13.6.3.2 The first phase188

13.6.3.3 The second phase188

13.6.3.4 Input types188

13.6.3.5 Output types189

13.6.3.6 Dependence189

13.6.3.7 Output type inferences189

13.6.3.8 Explicit parameter type inferences189

13.6.3.9 Exact inferences189

13.6.3.10 Lower-bound inferences189

13.6.3.11 Upper-bound inferences190

13.6.3.12 Fixing191

13.6.3.13 Inferred return type191

13.6.3.14 Type inference for conversion of method groups192

13.6.3.15 Finding the best common type of a set of expressions193

13.6.4 Overload resolution193

13.6.4.1 General193

13.6.4.2 Applicable function member194

13.6.4.3 Better function member194

13.6.4.4 Better conversion from expression196

13.6.4.5 Better conversion from type197

13.6.4.6 Better conversion target197

13.6.4.7 Overloading in generic classes197

13.6.5 Compile-time checking of dynamic member invocation198

13.6.6 Function member invocation199

13.6.6.1 General199

13.6.6.2 Invocations on boxed instances200

13.7 Primary expressions200

13.7.1 General200

13.7.2 Literals201

13.7.3 Simple names201

13.7.3.1 General201

13.7.3.2 Invariant meaning in blocks203

13.7.4 Parenthesized expressions204

13.7.5 Member access204

13.7.5.1 General204

13.7.5.2 Identical simple names and type names206

13.7.6 Invocation expressions206

13.7.6.1 General206

13.7.6.2 Method invocations207

13.7.6.3 Extension method invocations208

13.7.6.4 Delegate invocations211

13.7.7 Element access211

13.7.7.1 General211

13.7.7.2 Array access212

13.7.7.3 Indexer access212

13.7.8 This access213

13.7.9 Base access214

13.7.10 Postfix increment and decrement operators214

13.7.11 The new operator216

13.7.11.1 General216

13.7.11.2 Object creation expressions216

13.7.11.3 Object initializers218

13.7.11.4 Collection initializers220

13.7.11.5 Array creation expressions221

13.7.11.6 Delegate creation expressions223

13.7.11.7 Anonymous object creation expressions226

13.7.12 The typeof operator228

13.7.13 The sizeof operator229

13.7.14 The checked and unchecked operators230

13.7.15 Default value expressions232

13.7.16 Anonymous method expressions233

13.8 Unary operators240

13.8.1 General240

13.8.2 Unary plus operator240

13.8.3 Unary minus operator240

13.8.4 Logical negation operator241

13.8.5 Bitwise complement operator241

13.8.6 Prefix increment and decrement operators242

13.8.7 Cast expressions243

13.8.8 Await expressions244

13.8.8.1 General244

13.8.8.2 Awaitable expressions244

13.8.8.3 Classification of await expressions245

13.8.8.4 Run-time evaluation of await expressions245

13.9 Arithmetic operators245

13.9.1 General245

13.9.2 Multiplication operator246

13.9.3 Division operator247

13.9.4 Remainder operator248

13.9.5 Addition operator249

13.9.6 Subtraction operator251

13.10 Shift operators253

13.11 Relational and type-testing operators255

13.11.1 General255

13.11.2 Integer comparison operators255

13.11.3 Floating-point comparison operators256

13.11.4 Decimal comparison operators257

13.11.5 Boolean equality operators257

13.11.6 Enumeration comparison operators257

13.11.7 Reference type equality operators258

13.11.8 String equality operators260

13.11.9 Delegate equality operators261

13.11.10 Equality operators between nullable value types and the null literal262

13.11.11 The is operator262

13.11.12 The as operator264

13.12 Logical operators265

13.12.1 General265

13.12.2 Integer logical operators266

13.12.3 Enumeration logical operators266

13.12.4 Boolean logical operators267

13.12.5 Nullable Boolean & and | operators267

13.13 Conditional logical operators268

13.13.1 General268

13.13.2 Boolean conditional logical operators268

13.13.3 User-defined conditional logical operators269

13.14 The null coalescing operator269

13.15 Conditional operator270

13.16 Anonymous function expressions271

13.16.1 General271

13.16.2 Anonymous function signatures273

13.16.3 Anonymous function bodies273

13.16.4 Overload resolution274

13.16.5 Anonymous functions and dynamic binding275

13.16.6 Outer variables275

13.16.6.1 General275

13.16.6.2 Captured outer variables275

13.16.6.3 Instantiation of local variables276

13.16.7 Evaluation of anonymous function expressions278

13.17 Query expressions278

13.17.1 General278

13.17.2 Ambiguities in query expressions279

13.17.3 Query expression translation279

13.17.3.1 General279

13.17.3.2 Select and groupby clauses with continuations280

13.17.3.3 Explicit range variable types280

13.17.3.4 Degenerate query expressions281

13.17.3.5 From, let, where, join and orderby clauses281

13.17.3.6 Select clauses285

13.17.3.7 Groupby clauses285

13.17.3.8 Transparent identifiers285

13.17.4 The query expression pattern287

13.18 Assignment operators288

13.18.1 General288

13.18.2 Simple assignment288

13.18.3 Compound assignment290

13.18.4 Event assignment291

13.19 Expression292

13.20 Constant expressions292

13.21 Boolean expressions293

14. Statements295

14.1 General295

14.2 End points and reachability295

14.3 Blocks297

14.3.1 General297

14.3.2 Statement lists297

14.4 The empty statement298

14.5 Labeled statements298

14.6 Declaration statements299

14.6.1 General299

14.6.2 Local variable declarations299

14.6.3 Local constant declarations300

14.7 Expression statements301

14.8 Selection statements301

14.8.1 General301

14.8.2 The if statement302

14.8.3 The switch statement302

14.9 Iteration statements306

14.9.1 General306

14.9.2 The while statement306

14.9.3 The do statement306

14.9.4 The for statement307

14.9.5 The foreach statement308

14.10 Jump statements311

14.10.1 General311

14.10.2 The break statement312

14.10.3 The continue statement313

14.10.4 The goto statement313

14.10.5 The return statement314

14.10.6 The throw statement315

14.11 The try statement316

14.12 The checked and unchecked statements319

14.13 The lock statement320

14.14 The using statement321

14.15 The yield statement324

15. Namespaces327

15.1 General327

15.2 Compilation units327

15.3 Namespace declarations327

15.4 Extern alias directives329

15.5 Using directives329

15.5.1 General329

15.5.2 Using alias directives330

15.5.3 Using namespace directives336

15.6 Namespace member declarations338

15.7 Type declarations338

15.8 Qualified alias member339

15.8.1 General339

15.8.2 Uniqueness of aliases341

16. Classes343

16.1 General343

16.2 Class declarations343

16.2.1 General343

16.2.2 Class modifiers343

16.2.2.1 General343

16.2.2.2 Abstract classes344

16.2.2.3 Sealed classes344

16.2.2.4 Static classes345

16.2.3 Type parameters346

16.2.4 Class base specification347

16.2.4.1 General347

16.2.4.2 Base classes347

16.2.4.3 Interface implementations349

16.2.5 Type parameter constraints350

16.2.6 Class body355

16.2.7 Partial declarations355

16.3 Class members362

16.3.1 General362

16.3.2 The instance type364

16.3.3 Members of constructed types364

16.3.4 Inheritance365

16.3.5 The new modifier367

16.3.6 Access modifiers367

16.3.7 Constituent types367

16.3.8 Static and instance members367

16.3.9 Nested types368

16.3.9.1 General368

16.3.9.2 Fully qualified name369

16.3.9.3 Declared accessibility369

16.3.9.4 Hiding369

16.3.9.5 this access370

16.3.9.6 Access to private and protected members of the containing type371

16.3.9.7 Nested types in generic classes372

16.3.10 Reserved member names372

16.3.10.1 General372

16.3.10.2 Member names reserved for properties373

16.3.10.3 Member names reserved for events373

16.3.10.4 Member names reserved for indexers373

16.3.10.5 Member names reserved for finalizers374

16.4 Constants374

16.5 Fields375

16.5.1 General375

16.5.2 Static and instance fields377

16.5.3 Readonly fields377

16.5.3.1 General377

16.5.3.2 Using static readonly fields for constants377

16.5.3.3 Versioning of constants and static readonly fields377

16.5.4 Volatile fields378

16.5.5 Field initialization379

16.5.6 Variable initializers380

16.5.6.1 General380

16.5.6.2 Static field initialization380

16.5.6.3 Instance field initialization382

16.6 Methods382

16.6.1 General382

16.6.2 Method parameters385

16.6.2.1 General385

16.6.2.2 Value parameters386

16.6.2.3 Reference parameters387

16.6.2.4 Output parameters387

16.6.2.5 Parameter arrays388

16.6.3 Static and instance methods390

16.6.4 Virtual methods391

16.6.5 Override methods393

16.6.6 Sealed methods395

16.6.7 Abstract methods396

16.6.8 External methods397

16.6.9 Partial methods398

16.6.10 Extension methods400

16.6.11 Method body401

16.7 Properties402

16.7.1 General402

16.7.2 Static and instance properties403

16.7.3 Accessors403

16.7.4 Automatically implemented properties408

16.7.5 Accessibility409

16.7.6 Virtual, sealed, override, and abstract accessors410

16.8 Events412

16.8.1 General412

16.8.2 Field-like events414

16.8.3 Event accessors417

16.8.4 Static and instance events419

16.8.5 Virtual, sealed, override, and abstract accessors419

16.9 Indexers419

16.10 Operators423

16.10.1 General423

16.10.2 Unary operators424

16.10.3 Binary operators425

16.10.4 Conversion operators425

16.11 Instance constructors428

16.11.1 General428

16.11.2 Constructor initializers429

16.11.3 Instance variable initializers430

16.11.4 Constructor execution430

16.11.5 Default constructors431

16.12 Static constructors433

16.13 Finalizers435

16.14 Iterators437

16.14.1 General437

16.14.2 Enumerator interfaces437

16.14.3 Enumerable interfaces437

16.14.4 Yield type437

16.14.5 Enumerator objects437

16.14.5.1 General437

16.14.5.2 The MoveNext method438

16.14.5.3 The Current property439

16.14.5.4 The Dispose method439

16.14.6 Enumerable objects440

16.14.6.1 General440

16.14.6.2 The GetEnumerator method440

16.15 Async Functions447

16.15.1 General447

16.15.2 Evaluation of a task-returning async function447

16.15.3 Evaluation of a void-returning async function448

17. Structs449

17.1 General449

17.2 Struct declarations449

17.2.1 General449

17.2.2 Struct modifiers449

17.2.3 Partial modifier450

17.2.4 Struct interfaces450

17.2.5 Struct body450

17.3 Struct members450

17.4 Class and struct differences451

17.4.1 General451

17.4.2 Value semantics451

17.4.3 Inheritance452

17.4.4 Assignment452

17.4.5 Default values452

17.4.6 Boxing and unboxing453

17.4.7 Meaning of this455

17.4.8 Field initializers455

17.4.9 Constructors455

17.4.10 Static constructors456

17.4.11 Automatically implemented properties456

18. Arrays461

18.1 General461

18.2 Array types461

18.2.1 General461

18.2.2 The System.Array type462

18.2.3 Arrays and the generic collection interfaces462

18.3 Array creation463

18.4 Array element access464

18.5 Array members464

18.6 Array covariance464

18.7 Array initializers464

19. Interfaces467

19.1 General467

19.2 Interface declarations467

19.2.1 General467

19.2.2 Interface modifiers467

19.2.3 Variant type parameter lists468

19.2.3.1 General468

19.2.3.2 Variance safety468

19.2.3.3 Variance conversion469

19.2.4 Base interfaces469

19.3 Interface body471

19.4 Interface members471

19.4.1 General471

19.4.2 Interface methods472

19.4.3 Interface properties473

19.4.4 Interface events473

19.4.5 Interface indexers473

19.4.6 Interface member access474

19.5 Fully qualified interface member names475

19.6 Interface implementations476

19.6.1 General476

19.6.2 Explicit interface member implementations477

19.6.3 Uniqueness of implemented interfaces479

19.6.4 Implementation of generic methods480

19.6.5 Interface mapping481

19.6.6 Interface implementation inheritance484

19.6.7 Interface re-implementation486

19.6.8 Abstract classes and interfaces487

20. Enums489

20.1 General489

20.2 Enum declarations489

20.3 Enum modifiers489

20.4 Enum members490

20.5 The System.Enum type492

20.6 Enum values and operations492

21. Delegates493

21.1 General493

21.2 Delegate declarations493

21.3 Delegate Members496

21.4 Delegate compatibility496

21.5 Delegate instantiation497

21.6 Delegate invocation497

22. Exceptions501

22.1 General501

22.2 Causes of exceptions501

22.3 The System.Exception class501

22.4 How exceptions are handled502

22.5 Common exception classes502

23. Attributes505

23.1 General505

23.2 Attribute classes505

23.2.1 General505

23.2.2 Attribute usage505

23.2.3 Positional and named parameters507

23.2.4 Attribute parameter types507

23.3 Attribute specification508

23.4 Attribute instances517

23.4.1 General517

23.4.2 Compilation of an attribute517

23.4.3 Run-time retrieval of an attribute instance517

23.5 Reserved attributes519

23.5.1 General519

23.5.2 The AttributeUsage attribute519

23.5.3 The Conditional attribute520

23.5.3.1 General520

23.5.3.2 Conditional methods520

23.5.3.3 Conditional attribute classes523

23.5.4 The Obsolete attribute524

23.5.5 Caller-info attributes525

23.5.5.1 General525

23.5.5.2 The CallerLineNumber attribute526

23.5.5.3 The CallerFilePath attribute526

23.5.5.4 The CallerMemberName attribute526

23.6 Attributes for interoperation527

24. Unsafe code571

24.1 General571

24.2 Unsafe contexts571

24.3 Pointer types574

24.4 Fixed and moveable variables576

24.5 Pointer conversions577

24.5.1 General577

24.5.2 Pointer arrays578

24.6 Pointers in expressions579

24.6.1 General579

24.6.2 Pointer indirection580

24.6.3 Pointer member access580

24.6.4 Pointer element access581

24.6.5 The address-of operator581

24.6.6 Pointer increment and decrement582

24.6.7 Pointer arithmetic583

24.6.8 Pointer comparison584

24.6.9 The sizeof operator584

24.7 The fixed statement584

24.8 Fixed-size buffers588

24.8.1 General588

24.8.2 Fixed-size buffer declarations588

24.8.3 Fixed-size buffers in expressions589

24.8.4 Definite assignment checking590

24.9 Stack allocation590

Annex A. Grammar595

A.1 General595

A.2 Lexical grammar595

A.2.1 Comments596

A.2.2 Tokens596

A.2.3 Keywords598

A.2.4 Operators and punctuators600

A.2.5 Pre-processing directives600

A.3 Syntactic grammar603

A.3.1 Basic concepts603

A.3.2 Types603

A.3.3 Variables604

A.3.4 Expressions605

A.3.5 Statements611

A.3.6 Namespaces614

A.3.7 Classes615

A.3.8 Structs621

A.3.9 Arrays621

A.3.10 Interfaces622

A.3.11 Enums623

A.3.12 Delegates624

A.3.13 Attributes624

A.4 Grammar extensions for unsafe code625

Annex B. Portability issues629

B.1 General629

B.2 Undefined behavior629

B.3 Implementation-defined behavior629

B.4 Unspecified behavior630

B.5 Other Issues631

Annex C. Standard library635

C.1 General635

C.2 Standard Library Types defined in ISO/IEC 23271635

C.3 Standard Library Types not defined in ISO/IEC 23271:2012644

Annex D. Documentation comments647

D.1 General647

D.2 Introduction647

D.3 Recommended tags648

D.3.1 General648

D.3.2 649

D.3.3 649

D.3.4 650

D.3.5 650

D.3.6 650

D.3.7 651

D.3.8 652

D.3.9 653

D.3.10 653

D.3.11 653

D.3.12 654

D.3.13 654

D.3.14 655

D.3.15 655

D.3.16 655

D.3.17 656

D.3.18 656

D.3.19 656

D.4 Processing the documentation file657

D.4.1 General657

D.4.2 ID string format657

D.4.3 ID string examples658

D.5 An example662

D.5.1 C# source code662

D.5.2 Resulting XML664

Annex E. Bibliography667

ECMA-334

Table of Contents

66

67

Foreword

This Standard replaces ECMA-334:2006. Changes from the previous edition include the following:

Addition of

#pragma warning preprocessing directive

default and hidden options on the #line preprocessing directive

dynamic type

implicit typing

fixed-size buffers in unsafe code

caller info attributes

async functions

query expressions

Removal of

unqualified names

concept of a null type

Integration of

nullable value types

generic types and functions

iterators

Introduction

This International Standard is based on a submission that was originally from Hewlett-Packard, Intel, and Microsoft, that described a language calledC#, which was developed within Microsoft. The principal inventors of this language were Anders Hejlsberg, Scott Wiltamuth, and Peter Golde. The first widely distributed implementation of C# was released by Microsoft in July 2000, as part of its .NET Framework initiative.

Ecma Technical Committee39 (TC39) Task Group2 (TG2) was formed in September 2000, to produce a standard forC#. Another Task Group, TG3, was also formed at that time to produce a standard for a library and execution environment called Common Language Infrastructure (CLI). (CLI is based on a subset of the .NET Framework.) Although Microsofts implementation of C# relies on CLI for library and run-time support, other implementations of C# need not, provided they support an alternate way of getting at the minimum CLI features required by this C#standard (see Annex C).

As the definition of C# evolved, the goals used in its design were as follows:

C# is intended to be a simple, modern, general-purpose, object-oriented programming language.

The language, and implementations thereof, should provide support for software engineering principles such as strong type checking, array bounds checking, detection of attempts to use uninitialized variables, and automatic garbage collection. Software robustness, durability, and programmer productivity are important.

The language is intended for use in developing software components suitable for deployment in distributed environments.

Source code portability is very important, as is programmer portability, especially for those programmers already familiar withC andC++.

Support for internationalization is very important.

C# is intended to be suitable for writing applications for both hosted and embedded systems, ranging from the very large that use sophisticated operating systems, down to the very small having dedicated functions.

Although C#applications are intended to be economical with regard to memory and processing power requirements, the language was not intended to compete directly on performance and size with C or assembly language.

A second edition was produced in 2006, which incorporated support for generics and iterators, among other things. Subsequently, committee Ecma TC39/TG2 was renamed to TC49/TG2.

The development of this version of the standard started in October 2014.

Introduction

Scope

This International Standard specifies the form and establishes the interpretation of programs written in the C#programming language. It specifies

The representation of C#programs;

The syntax and constraints of the C#language;

The semantic rules for interpreting C#programs;

The restrictions and limits imposed by a conforming implementation ofC#.

This International Standard does not specify

The mechanism by which C#programs are transformed for use by a data-processing system;

The mechanism by which C#applications are invoked for use by a data-processing system;

The mechanism by which input data are transformed for use by a C#application;

The mechanism by which output data are transformed after being produced by a C#application;

The size or complexity of a program and its data that will exceed the capacity of any specific data-processing system or the capacity of a particular processor;

All minimal requirements of a data-processing system that is capable of supporting a conforming implementation.

8 Lexical structure

Conformance

Conformance is of interest to the following audiences:

Those designing, implementing, or maintaining C#implementations.

Governmental or commercial entities wishing to procure C#implementations.

Testing organizations wishing to provide a C#conformance test suite.

Programmers wishing to port code from one C#implementation to another.

Educators wishing to teach StandardC#.

Authors wanting to write about StandardC#.

As such, conformance is most important, and the bulk of this International Standard is aimed at specifying the characteristics that make C#implementations and C#programs conforming ones.

The text in this International Standard that specifies requirements is considered normative. All other text in this specification is informative; that is, for information purposes only. Unless stated otherwise, all text is normative. Normative text is further broken into required and conditional categories. Conditionally normative text specifies a feature and its requirements where the feature is optional. However, if that feature is provided, its syntax and semantics shall must be exactly as specified.

Undefined behavior is indicated in this International Standard only by the words undefined behavior.

A strictly conforming program shall use only those features of the language specified in this International Standard as being required. (This means that a strictly conforming program cannot use any conditionally normative feature.) It shall not produce output dependent on any unspecified, undefined, or implementation-defined behavior.

A conforming implementation of C# shall must accept any strictly conforming program.

A conforming implementation of C# shall must provide and support all the types, values, objects, properties, methods, and program syntax and semantics described in the normative (but not the conditionally normative) parts in this International Standard.

A conforming implementation of C# shall interpret characters in conformance with the Unicode Standard, Version4.0, and ISO/IEC 10646-1. Conforming implementations shall must accept Unicode source files encoded with the UTF-8 encoding form.

A conforming implementation of C# shall not successfully translate source containing a #error preprocessing directive unless it is part of a group skipped by conditional compilation.

A conforming implementation of C# shall produce at least one diagnostic message if the source program violates any rule of syntax, or any negative requirement (defined as a shall or shall not or error or warning requirement), unless that requirement is marked with the words no diagnostic is required.

A conforming implementation of C# is permitted to provide additional types, values, objects, properties, and methods beyond those described in this International Standard, provided they do not alter the behavior of any strictly conforming program. Conforming implementations are required to diagnose programs that use extensions that are ill formed according to this International Standard. Having done so, however, they can compile and execute such programs. (The ability to have extensions implies that a conforming implementation reserves no identifiers other than those explicitly reserved in this International Standard.)

A conforming implementation of C# shall be accompanied by a document that defines all implementation-defined characteristics, and all extensions.

A conforming implementation of C# shall support the class library documented inAnnex C. This library is included by reference in this International Standard.

A conforming program is one that is acceptable to a conforming implementation. (Such a program is permitted to contain extensions or conditionally normative features.)

Normative references

The following normative documents contain provisions, which, through reference in this text, constitute provisions of this International Standard. For dated references, subsequent amendments to, or revisions of, any of these publications do not apply. However, parties to agreements based on this International Standard are encouraged to investigate the possibility of applying the most recent editions of the normative documents indicated below. For undated references, the latest edition of the normative document referred to applies. Members of ISO and IEC maintain registers of currently valid International Standards.

ISO/IEC 23271:201205, Common Language Infrastructure (CLI), PartitionIV: Base Class Library (BCL), Extended Numerics Library, and Extended Array Library.

ISO 31.11:1992, Quantities and units Part 11: Mathematical signs and symbols for use in the physical sciences and technology.

ISO/IEC 2382.1:1993, Information technology Vocabulary Part 1: Fundamental terms.

ISO/IEC 10646 (all parts), Information technology Universal Multiple-Octet Coded Character Set (UCS).

IEC 60559:1989, Binary floating-point arithmetic for microprocessor systems (previously designated IEC 559:1989). (This standard is widely known by its U.S. national designation, ANSI/IEEE Standard 754-1985, IEEE Standard for Binary Floating-Point Arithmetic.)

The Unicode Consortium. The Unicode Standard, http://www.unicode.org/standard/standard.htmlVersion4.0, defined by: The Unicode Standard, Version4.0 (Boston, MA, Addison-Wesley, 2003. ISBN 0-321-18578-1).

Terms and definitions

For the purposes of this International Standard, the following definitions apply. Other terms are defined where they appear in italic type or on the left side of a syntax rule. Terms explicitly defined in this International Standard are not to be presumed to refer implicitly to similar terms defined elsewhere. Terms not defined in this International Standard are to be interpreted according to ISO/IEC 2382.1. Mathematical symbols not defined in this International Standard are to be interpreted according to ISO 31.11.

4.1applicationassembly with an entry pointrefers to an assembly that has an entry point ( REF _Ref501033702 \r \h 9.1). When an application is run, a new application domain is created. Several different instantiations of an application can exist on the same machine at the same time, and each has its own application domain.

4.2application domainentity that enables application isolation by acting as a container for application state. An application domain acts as a container and boundary for the types defined in the application and the class libraries it uses. Types loaded into one application domain are distinct from the same type loaded into another application domain, and instances of objects are not directly shared between application domains. For instance, each application domain has its own copy of static variables for these types, and a static constructor for a type is run at most once per application domain. Implementations are free to provide implementation-specific policy or mechanisms for the creation and destruction of application domains.

4.3argumentexpression in the comma-separated list bounded by the parentheses in a method or instance constructor call expression or bounded by the square brackets in an element access expression. It is also known as an actual argument.

4.4assemblyone or more files output by the compiler as a result of program compilation. An assembly is a configured set of loadable code modules and other resources that together implement a unit of functionality. An assembly can contain types, the executable code used to implement these types, and references to other assemblies. The physical representation of an assembly is not defined by this specification. Essentially, an assembly is the output of the compiler.

4.5behaviorexternal appearance or action

4.6behavior, implementation-definedunspecified behavior where each implementation documents how the choice is made

4.7behavior, undefinedbehavior, upon use of a non-portable or erroneous construct or of erroneous data, for which this International Standard imposes no requirements. [Possible handling of undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message)].

4.8behavior, unspecifiedbehavior where this International Standard provides two or more possibilities and imposes no further requirements on which is chosen in any instance.

4.9character (when used without a qualifier)a) In the context of a non-Unicode encoding the meaning of character in that encoding; or

b) In the context of a character literal or a value of type char a Unicode code point in the range U+0000 to U+FFFF (including surrogate code points), that is a UTF-16 code unit; or

c) Otherwise a Unicode code point

4.10class libraryassembly that can be used by other assemblies. Use of a class library does not cause the creation of a new application domain. Instead, a class library is loaded into the application domain that uses it. For instance, when an application uses a class library, that class library is loaded into the application domain for that application. If an application uses a class libraryA that itself uses a class libraryB, then both A and B are loaded into the application domain for the application.

4.11diagnostic messagemessage belonging to an implementation-defined subset of the implementations output messages

4.12error, compile-timeerror reported during program translation

4.13exceptionerror condition that is outside the ordinary expected behaviorexceptional condition reported during program execution

4.14implementationparticular set of software (running in a particular translation environment under particular control options) that performs translation of programs for, and supports execution of methods in, a particular execution environment

4.15namespacelogical organizational system that provides a way of presentinggrouping related program elements that are exposed to other programs

4.16parametervariable declared as part of a method, instance constructor, operator, or indexer definition, which acquires a value on entry to that function member. It is also known as a formal parameter.

4.17programone or more source files that are presented to the compiler. Essentially, a program is the input to the compiler.

4.18program, validC#program constructed according to the syntax rules and diagnosable semantic rules

4.19program instantiationexecution of an application

STYLEREF "Heading 1" \n \* MERGEFORMAT 4. SEQ TermsAndDefsLevel1 \n 20recommended practicespecification that is strongly recommended, as being aligned with the intent of the standard, but that might be impractical for some implementations

4.20source fileordered sequence of Unicode characters. Source files typically have a one-to-one correspondence with files in a file system, but this correspondence is not required.

4.21unsafe codecode that is permitted to perform such lower-level operations as declaring and operating on pointers, performing conversions between pointers and integral types, and taking the address of variables. Such operations provide functionality such as permitting interfacing with the underlying operating system, accessing a memory-mapped device, or implementing a time-critical algorithm.

4.22warning, compile-timeinformational message reported during program translation, which is intended to identify a potentially questionable usage of a program element

Notational conventions

Lexical and syntactic grammars for C# are interspersed throughout this specification. The lexical grammar defines how characters can be combined to form tokens ( REF _Ref462576650 \r \h \* MERGEFORMAT 9.4), the minimal lexical elements of the language. The syntactic grammar defines how tokens can be combined to make valid C#programs.

Grammar productions include both non-terminal and terminal symbols. In grammar productions, non-terminal symbols are shown in italic type, and terminal symbols are shown in a fixed-width font. Each non-terminal is defined by a set of productions. The first line of a set of productions is the name of the non-terminal, followed by one or two colons. One colon is used for a production in the syntactic grammar, two colons for a production in the lexical grammar. Each successive indented line contains the right-hand side for a production that has the non-terminal symbol as the left-hand side. For example:

class-modifier:newpublicprotectedinternalprivateabstractsealedstatic

defines the class-modifier non-terminal as having seven productions.

Alternatives are normally listed on separate lines, as shown above, though in cases where there are many alternatives, the phrase one of precedes a list of the options. This is simply shorthand for listing each of the alternatives on a separate line. For example:

decimal-digit: one of0 1 2 3 4 5 6 7 8 9

is equivalent to:

decimal-digit:0123456789

A subscripted suffix opt, as in identifieropt, is used as shorthand to indicate an optional symbol. The example:

for-statement:for ( for-initializeropt ; for-conditionopt ; for-iteratoropt ) embedded-statement

is equivalent to:

for-statement:for ( ; ; ) embedded-statementfor ( for-initializer ; ; ) embedded-statementfor ( ; for-condition ; ) embedded-statementfor ( ; ; for-iterator ) embedded-statementfor ( for-initializer ; for-condition ; ) embedded-statementfor ( ; for-condition ; for-iterator ) embedded-statementfor ( for-initializer ; ; for-iterator ) embedded-statementfor ( for-initializer ; for-condition ; for-iterator ) embedded-statement

All terminal characters are to be understood as the appropriate Unicode character from the range U+0020 to U+007F, as opposed to any similar-looking characters from other Unicode character ranges.

Acronyms and abbreviations

This clause is informative.

The following acronyms and abbreviations are used throughout this International Standard:

BCL Base Class Library, which provides types to represent the built-in data types of the CLI, simple file access, custom attributes, security attributes, string manipulation, formatting, streams, and collections.

CLI Common Language Infrastructure

CLS Common Language Specification

IEC the International Electrotechnical Commission

IEEE the Institute of Electrical and Electronics Engineers

ISO the International Organization for Standardization

The name C# is pronounced CSharp.

The name C# is written as the latin capital letterC (U+0043) followed by the number sign# (U+0023).

End of informative text.

General description

This text is informative.

This International Standard is intended to be used by implementers, academics, and application programmers. As such, it contains a considerable amount of explanatory material that, strictly speaking, is not necessary in a formal language specification.

This standard is divided into the following subdivisions:

Front matter (clauses16);

Language overview (clause7);

The language syntax, constraints, and semantics (clauses824);

Annexes

Examples are provided to illustrate possible forms of the constructions described. References are used to refer to related clauses. Notes are provided to give advice or guidance to implementers or programmers. Annexes provide additional information and summarize the information contained in this International Standard.

Clauses14, part of Clause6, Clauses 823, the beginning of Clause24, and most of Annex D form a normative part of this standard. With the exception of the beginning, all of Clause24 is conditionally normative. The Foreword, Introduction, Clause5, part of Clause6, Clause7, Annexes A, B, C, part of AnnexesD, E, andF, notes, and examples are informative.

End of informative text.

Informative text is indicated in the following ways:

1. Whole or partial clauses or annexes delimited by This clause/text is informativeand End of informative text.

2. [Example: The following example code fragment, possibly with some narrative end example]

3. [Note: narrative end note]

All text not marked as being informative is normative.

Language overview

This clause is informative.

General

C# (pronounced See Sharp) is a simple, modern, object-oriented, and type-safe programming language. C# has its roots in the Cfamily of languages and will be immediately familiar toC, C++, and Java programmers.

C# is an object-oriented language, but C#further includes support for component-oriented programming. Contemporary software design increasingly relies on software components in the form of self-contained and self-describing packages of functionality. Key to such components is that they present a programming model with properties, methods, and events; they have attributes that provide declarative information about the component; and they incorporate their own documentation. C# provides language constructs to support directly these concepts, makingC# a very natural language in which to create and use software components.

Several C#features aid in the construction of robust and durable applications: Garbage collection automatically reclaims memory occupied by unused objects; exception handling provides a structured and extensible approach to error detection and recovery; and the type-safe design of the language makes it impossible to read from uninitialized variables, to index arrays beyond their bounds, or to perform unchecked type casts.

C# has a unified type system. All C#types, including primitive types such as int and double, inherit from a single root object type. Thus, all types share a set of common operations, and values of any type can be stored, transported, and operated upon in a consistent manner. Furthermore, C#supports both user-defined reference types and value types, allowing dynamic allocation of objects as well as in-line storage of lightweight structures.

To ensure that C#programs and libraries can evolve over time in a compatible manner, much emphasis has been placed on versioning in C#sdesign. Many programming languages pay little attention to this issue, and, as a result, programs written in those languages break more often than necessary when newer versions of dependent libraries are introduced. Aspects of C#sdesign that were directly influenced by versioning considerations include the separate virtual and override modifiers, the rules for method overload resolution, and support for explicit interface member declarations.

The rest of this clause describes the essential features of the C#language. Although later clauses describe rules and exceptions in a detail-oriented and sometimes mathematical manner, this clause strives for clarity and brevity at the expense of completeness. The intent is to provide the reader with an introduction to the language that will facilitate the writing of early programs and the reading of later clauses.

Hello world

The Hello, World program is traditionally used to introduce a programming language. Here it is inC#:

using System;

class Hello{static void Main() {Console.WriteLine("Hello, World");}}

C#source files typically have the file extension .cs. Assuming that the Hello, World program is stored in the file hello.cs, the program might be compiled using the command line

csc hello.cs

which produces an executable assembly named hello.exe. The output produced by this application when it is run is

Hello, World

The Hello, World program starts with a using directive that references the System namespace. Namespaces provide a hierarchical means of organizing C#programs and libraries. Namespaces contain types and other namespacesfor example, the System namespace contains a number of types, such as the Console class referenced in the program, and a number of other namespaces, such as IO and Collections. A using directive that references a given namespace enables unqualified use of the types that are members of that namespace. Because of the using directive, the program can use Console.WriteLine as shorthand for System.Console.WriteLine.

The Hello class declared by the Hello, World program has a single member, the method named Main. The Main method is declared with the static modifier. While instance methods can reference a particular enclosing object instance using the keyword this, static methods operate without reference to a particular object. By convention, a static method named Main serves as the entry point of a program.

The output of the program is produced by the WriteLine method of the Console class in the System namespace. This class is provided by the standard class libraries, which, by default, are automatically referenced by the compiler.

Program structure

The key organizational concepts in C# are programs, namespaces, types, members, and assemblies. C#programs consist of one or more source files. Programs declare types, which contain members and can be organized into namespaces. Classes and interfaces are examples of types. Fields, methods, properties, and events are examples of members. When C#programs are compiled, they are physically packaged into assemblies. Assemblies typically have the file extension .exe or .dll, depending on whether they implement applications or libraries, respectively.

The example

using System;

namespace Acme.Collections{public class Stack{Entry top;

public void Push(object data) {top = new Entry(top, data);}

public object Pop() {if (top == null) throw new InvalidOperationException();object result = top.data;top = top.next;return result;}

class Entry{public Entry next;public object data;

public Entry(Entry next, object data) {this.next = next;this.data = data;}}}}

declares a class named Stack in a namespace called Acme.Collections. The fully qualified name of this class is Acme.Collections.Stack. The class contains several members: a field named top, two methods named Push and Pop, and a nested class named Entry. The Entry class further contains three members: a field named next, a field named data, and a constructor. Assuming that the source code of the example is stored in the file acme.cs, the command line

csc /t:library acme.cs

compiles the example as a library (code without a Main entry point) and produces an assembly named acme.dll.

Assemblies contain executable code in the form of Intermediate Language (IL) instructions, and symbolic information in the form of metadata. Before it is executed, the IL code in an assembly is automatically converted to processor-specific code by the Just-In-Time (JIT) compiler of .NET Common Language Runtime.

Because an assembly is a self-describing unit of functionality containing both code and metadata, there is no need for #include directives and header files inC#. The public types and members contained in a particular assembly are made available in a C#program simply by referencing that assembly when compiling the program. For example, this program uses the Acme.Collections.Stack class from the acme.dll assembly:

using System;using Acme.Collections;

class Test{static void Main() {Stack s = new Stack();s.Push(1);s.Push(10);s.Push(100);Console.WriteLine(s.Pop());Console.WriteLine(s.Pop());Console.WriteLine(s.Pop());}}

If the program is stored in the file test.cs, when test.cs is compiled, the acme.dll assembly can be referenced using the compilers /roption:

csc /r:acme.dll test.cs

This creates an executable assembly named test.exe, which, when run, produces the output:

100101

C#permits the source text of a program to be stored in several source files. When a multi-file C#program is compiled, all of the source files are processed together, and the source files can freely reference each otherconceptually, it is as if all the source files were concatenated into one large file before being processed. Forward declarations are never needed inC# because, with very few exceptions, declaration order is insignificant. C#does not limit a source file to declaring only one public type nor does it require the name of the source file to match a type declared in the source file.

Types and variables

There are two kinds of types inC#: value types and reference types. Variables of value types directly contain their data whereas variables of reference types store references to their data, the latter being known as objects. With reference types, it is possible for two variables to reference the same object and thus possible for operations on one variable to affect the object referenced by the other variable. With value types, the variables each have their own copy of the data, and it is not possible for operations on one to affect the other (except in the case of ref and out parameter variables).

C#s value types are further divided into simple types, enum types, struct types, and nullable types, and C#s reference types are further divided into class types, interface types, array types, and delegate types.

The following table provides an overview of C#stype system.

Category

Description

Valuetypes

Simple types

Signed integral: sbyte, short, int, long

Unsigned integral: byte, ushort, uint, ulong

Unicode characters: char

IEEE floating point: float, double

High-precision decimal: decimal

Boolean: bool

Enum types

User-defined types of the form enum E {}

Struct types

User-defined types of the form struct S {}

Nullable types

Extensions of all other value types with a null value

Referencetypes

Class types

Ultimate base class of all other types: object

Unicode strings: string

User-defined types of the form class C {}

Interface types

User-defined types of the form interface I {}

Array types

Single- and multi-dimensional, for example, int[] and int[,]

Delegate types

User-defined types of the form e.g. delegate int D()

The eight integral types provide support for 8-bit, 16-bit, 32-bit, and 64-bit values in signed or unsigned form.

The two floating-point types, float and double, are represented using the 32-bit single-precision and 64-bit double-precision IEC-60559 formats, respectively.

The decimal type is a 128-bit data type suitable for financial and monetary calculations.

C#s bool type is used to represent Boolean valuesvalues that are either true or false.

Character and string processing in C# uses Unicode encoding. The char type represents a UTF-16 code unit, and the string type represents a sequence of UTF-16 code units.

The following table summarizes C#snumeric types.

Category

Bits

Type

Range/Precision

Signed integral

8

sbyte

128...127

16

short

32,768...32,767

32

int

2,147,483,648...2,147,483,647

64

long

9,223,372,036,854,775,808...9,223,372,036,854,775,807

Unsigned integral

8

byte

0...255

16

ushort

0...65,535

32

uint

0...4,294,967,295

64

ulong

0...18,446,744,073,709,551,615

Floating point

32

float

1.51045 to 3.41038, 7-digit precision

64

double

5.010324 to 1.710308, 15-digit precision

Decimal

128

decimal

1.01028 to 7.91028, 28-digit precision

C#programs use type declarations to create new types. A type declaration specifies the name and the members of the new type. Five of C#scategories of types are user-definable: class types, struct types, interface types, enum types, and delegate types.

A class type defines a data structure that contains data members (fields) and function members (methods, properties, and others). Class types support single inheritance and polymorphism, mechanisms whereby derived classes can extend and specialize base classes.

A struct type is similar to a class type in that it represents a structure with data members and function members. However, unlike classes, structs are value types and do not require heap allocation. Struct types do not support user-specified inheritance, and all struct types implicitly inherit from type object.

An interface type defines a contract as a named set of public function members. A class or struct that implements an interface must provide implementations of the interfaces function members. An interface may inherit from multiple base interfaces, and a class or struct may implement multiple interfaces.

A delegate type represents references to methods with a particular parameter list and return type. Delegates make it possible to treat methods as entities that can be assigned to variables and passed as parameters. Delegates are similar to the concept of function pointers found in some other languages, but unlike function pointers, delegates are object-oriented and type-safe.

Class, struct, interface and delegate types all support generics, whereby they can be parameterized with other types.

An enum type is a distinct type with named constants. Every enum type has an underlying type, which must be one of the eight integral types. The set of values of an enum type is the same as the set of values of the underlying type.

C# supports single- and multi-dimensional arrays of any type. Unlike the types listed above, array types do not have to be declared before they can be used. Instead, array types are constructed by following a type name with square brackets. For example, int[] is a single-dimensional array of int, int[,] is a two-dimensional array of int, and int[][] is a single-dimensional array of single-dimensional arrays of int.

Nullable types also do not have to be declared before they can be used. For each non-nullable value typeT there is a corresponding nullable typeT?, which can hold an additional value, null. For instance, int? is a type that can hold any 32-bit integer or the value null.

C#stype system is unified such that a value of any type can be treated as an object. Every type in C# directly or indirectly derives from the object class type, and object is the ultimate base class of all types. Values of reference types are treated as objects simply by viewing the values as type object. Values of value types are treated as objects by performing boxing and unboxing operations. In the following example, an int value is converted to object and back again to int.

using System;

class Test{static void Main() {int i = 123;object o = i;// Boxingint j = (int)o;// Unboxing}}

When a value of a value type is converted to type object, an object instance, also called a box, is allocated to hold the value, and the value is copied into that box. Conversely, when an object reference is cast to a value type, a check is made that the referenced object is a box of the correct value type, and, if the check succeeds, the value in the box is copied out.

C#sunified type system effectively means that value types can become objects on demand. Because of the unification, general-purpose libraries that use type object can be used with both reference types and value types.

There are several kinds of variables inC#, including fields, array elements, local variables, and parameters. Variables represent storage locations, and every variable has a type that determines what values can be stored in the variable, as shown by the following table.

Type of Variable

Possible Contents

Non-nullable value type

A value of that exact type

Nullable value type

A null value or a value of that exact type

object

A null reference, a reference to an object of any reference type, or a reference to a boxed value of any value type

Class type

A null reference, a reference to an instance of that class type, or a reference to an instance of a class derived from that class type

Interface type

A null reference, a reference to an instance of a class type that implements that interface type, or a reference to a boxed value of a value type that implements that interface type

Array type

A null reference, a reference to an instance of that array type, or a reference to an instance of a compatible array type

Delegate type

A null reference or a reference to an instance of that delegate type

Expressions

Expressions are constructed from operands and operators. The operators of an expression indicate which operations to apply to the operands. Examples of operators include+, -, *, /, and new. Examples of operands include literals, fields, local variables, and expressions.

When an expression contains multiple operators, the precedence of the operators controls the order in which the individual operators are evaluated. For example, the expression x+y*z is evaluated as x+(y*z) because the *operator has higher precedence than the +operator.

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:

Except for the assignment operators, all binary operators are left-associative, meaning that operations are performed from left to right. For example, x+y+z is evaluated as(x+y)+z.

The assignment operators and the conditional operator (?:) are right-associative, meaning that operations are performed from right to left. For example, x=y=z is evaluated as x=(y=z).

Precedence and associativity can be controlled using parentheses. For example, x+y*z first multipliesy byz and then adds the result tox, but (x+y)*z first addsx andy and then multiplies the result byz.

Most 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.

The following table summarizes C#s operators, listing the operator categories in order of precedence from highest to lowest. Operators in the same category have equal precedence.

Category

Expression

Description

Primary ( REF _Ref486766991 \r \h \* MERGEFORMAT 13.7)

x.m

Member access

x()

Method and delegate invocation

x[]

Array and indexer access

x++

Post-increment

x--

Post-decrement

new T()

Object and delegate creation

new T(){}

Object creation with initializer

new {}

Anonymous object initializer

new T[]

Array creation

typeof(T)

Obtain System.Type object forT

checked(x)

Evaluate expression in checked context

unchecked(x)

Evaluate expression in unchecked context

default(T)

Obtain default value of typeT

delegate {...}

Anonymous function (anonymous method)

Unary ( REF _Ref372379001 \r \h 13.8)

+x

Identity

-x

Negation

!x

Logical negation

~x

Bitwise negation

++x

Pre-increment

--x

Pre-decrement

(T)x

Explicitly convert x to type T

await x

Asynchronously wait for x to complete

Multiplicative ( REF _Ref370394205 \r \h \* MERGEFORMAT 13.9)

x * y

Multiplication

x / y

Division

x % y

Remainder

Additive ( REF _Ref370394205 \r \h \* MERGEFORMAT 13.9)

x + y

Addition, string concatenation, delegate combination

x y

Subtraction, delegate removal

Shift ( REF _Ref493868012 \r \h \* MERGEFORMAT 13.10)

x > y

Shift right

Relational and type testing ( REF _Ref461974763 \r \h \* MERGEFORMAT 13.11)

x < y

Less than

x > y

Greater than

x = y

Greater than or equal

x is T

Return true ifx is aT, false otherwise

x as T

Returnx typed asT, or null ifx is not aT

Equality ( REF _Ref461974763 \r \h \* MERGEFORMAT 13.11)

x == y

Equal

x != y

Not equal

Logical AND ( REF _Ref461974981 \r \h \* MERGEFORMAT 13.12)

x & y

Integer bitwise AND, boolean logical AND

Logical XOR ( REF _Ref461974981 \r \h \* MERGEFORMAT 13.12)

x ^ y

Integer bitwise XOR, boolean logical XOR

Logical OR ( REF _Ref461974981 \r \h \* MERGEFORMAT 13.12)

x | y

Integer bitwise OR, boolean logical OR

Conditional AND ( REF _Ref461975001 \r \h \* MERGEFORMAT 13.13)

x && y

Evaluatesy only ifx is true

Conditional OR ( REF _Ref461975001 \r \h \* MERGEFORMAT 13.13)

x || y

Evaluatesy only ifx is false

Null coalescing ( REF _Ref93160010 \r \h \* MERGEFORMAT 13.14)

X ?? y

Evaluates toy ifx is null, tox otherwise

Conditional ( REF _Ref370394596 \r \h \* MERGEFORMAT 13.15)

x ? y : z

Evaluatesy ifx is true, z ifx is false

Assignment ( REF _Ref370394503 \r \h \* MERGEFORMAT 13.18) or anonymous function ( REF _Ref170644974 \r \h \* MERGEFORMAT 13.16)

x = y

Assignment

x op= y

Compound assignment; supported operators are

*= /= %= += -= = &= ^= |=

(T x) => y

Anonymous function (lambda expression)

Statements

The actions of a program are expressed using statements. C#supports several different kinds of statements, a number of which are defined in terms of embedded statements.

A block permits multiple statements to be written in contexts where a single statement is allowed. A block consists of a list of statements written between the delimiters{ and}.

Declaration statements are used to declare local variables and constants.

Expression statements are used to evaluate expressions. Expressions that can be used as statements include method invocations, object allocations using the new operator, assignments using = and the compound assignment operators, increment and decrement operations using the ++ and --operators and await expressions.

Selection statements are used to select one of a number of possible statements for execution based on the value of some expression. In this group are the if and switch statements.

Iteration statements are used to execute repeatedly an embedded statement. In this group are the while, do, for, and foreach statements.

Jump statements are used to transfer control. In this group are the break, continue, goto, throw, return, and yield statements.

The try...catch statement is used to catch exceptions that occur during execution of a block, and the try...finally statement is used to specify finalization code that is always executed, whether an exception occurred or not.

The checked and unchecked statements are used to control the overflow-checking context for integral-type arithmetic operations and conversions.

The lock statement is used to obtain the mutual-exclusion lock for a given object, execute a statement, and then release the lock.

The using statement is used to obtain a resource, execute a statement, and then dispose of that resource.

The following table lists the kinds of statements that can be used, and provides an example for each.

Statement

Example

Local variable declaration

static void Main() {int a; int b = 2, c = 3; a = 1;Console.WriteLine(a + b + c);}

Local constant declaration

static void Main() {const float pi = 3.1415927f;const int r = 25;Console.WriteLine(pi * r * r);}

Expression statement

static void Main() {int i;i = 123;// Expression statementConsole.WriteLine(i);// Expression statementi++;// Expression statementConsole.WriteLine(i);// Expression statement}

if statement

static void Main(string[] args) {if (args.Length == 0) {Console.WriteLine("No arguments");}else {Console.WriteLine("One or more arguments");}}

switch statement

static void Main(string[] args) {int n = args.Length;switch (n) {case 0:Console.WriteLine("No arguments");break;case 1:Console.WriteLine("One argument");break;default:Console.WriteLine("{0} arguments", n);break;}}}

while statement

static void Main(string[] args) {int i = 0;while (i < args.Length) {Console.WriteLine(args[i]);i++;}}

do statement

static void Main() {string s;do {s = Console.ReadLine();if (s != null) Console.WriteLine(s);} while (s != null);}

for statement

static void Main(string[] args) {for (int i = 0; i < args.Length; i++) {Console.WriteLine(args[i]);}}

foreach statement

static void Main(string[] args) {foreach (string s in args) {Console.WriteLine(s);}}

break statement

static void Main() {while (true) {string s = Console.ReadLine();if (s == null) break;Console.WriteLine(s);}}

continue statement

static void Main(string[] args) {for (int i = 0; i < args.Length; i++) {if (args[i].StartsWith("/")) continue;Console.WriteLine(args[i]);}}

goto statement

static void Main(string[] args) {int i = 0;goto check;loop:Console.WriteLine(args[i++]);check:if (i < args.Length) goto loop;}

return statement

static int Add(int a, int b) { return a + b;}

static void Main() { Console.WriteLine(Add(1, 2)); return;}

yield statement

static IEnumerable Range(int from, int to) {for (int i = from; i < to; i++) {yield return i;}yield break;}

static void Main() {foreach (int x in Range(-10,10)) {Console.WriteLine(x);}}

throw statements and try statements

static double Divide(double x, double y) {if (y == 0) throw new DivideByZeroException();return x / y;}

static void Main(string[] args) {try {if (args.Length != 2) {throw new Exception("Two numbers required");}double x = double.Parse(args[0]);double y = double.Parse(args[1]);Console.WriteLine(Divide(x, y));}catch (Exception e) {Console.WriteLine(e.Message);}finally {Console.WriteLine(Good bye!);}}

checked and unchecked statements

static void Main() { int x = int.MaxValue; checked { Console.WriteLine(x + 1); // Exception } unchecked { Console.WriteLine(x + 1); // Overflow }}

lock statement

class Account{decimal balance;

public void Withdraw(decimal amount) {lock (this) {if (amount > balance) {throw new Exception("Insufficient funds");}balance -= amount;}}}

using statement

static void Main() {using (TextWriter w = File.CreateText("test.txt")) {w.WriteLine("Line one");w.WriteLine("Line two");w.WriteLine("Line three");}}

Classes and objectsGeneral

Classes are the most fundamental of C#stypes. A class is a data structure that combines state (fields) and actions (methods and other function members) in a single unit. A class provides a definition for dynamically created instances of the class, also known as objects. Classes support inheritance and polymorphism, mechanisms whereby derived classes can extend and specialize base classes.

New classes are created using class declarations. A class declaration starts with a header that specifies the attributes and modifiers of the class, the name of the class, the base class (if given), and the interfaces implemented by the class. The header is followed by the class body, which consists of a list of member declarations written between the delimiters{ and}.

The following is a declaration of a simple class named Point:

public class Point{public int x, y;

public Point(int x, int y) {this.x = x;this.y = y;}}

Instances of classes are created using the new operator, which allocates memory for a new instance, invokes a constructor to initialize the instance, and returns a reference to the instance. The following statements create two Point objects and store references to those objects in two variables:

Point p1 = new Point(0, 0);Point p2 = new Point(10, 20);

The memory occupied by an object is automatically reclaimed when the object is no longer in use. It is neither necessary nor possible to explicitly deallocate objects inC#.

Members

The members of a class are either static members or instance members. Static members belong to classes, and instance members belong to objects (instances of classes).

The following table provides an overview of the kinds of members a class can contain.

Member

Description

Constants

Constant values associated with the class

Fields

Variables of the class

Methods

Computations and actions that can be performed by the class

Properties

Actions associated with reading and writing named properties of the class

Indexers

Actions associated with indexing instances of the class like an array

Events

Notifications that can be generated by the class

Operators

Conversions and expression operators supported by the class

Constructors

Actions required to initialize instances of the class or the class itself

Finalizers

Actions to perform before instances of the class are permanently discarded

Types

Nested types declared by the class

Accessibility

Each member of a class has an associated accessibility, which controls the regions of program text that are able to access the member. There are five possible forms of accessibility. These are summarized in the following table.

Accessibility

Meaning

public

Access not limited

protected

Access limited to this class or classes derived from this class

internal

Access limited to this program

protected internal

Access limited to this program or classes derived from this class

private

Access limited to this class

Type parameters

A class definition may specify a set of type parameters by following the class name with angle brackets enclosing a list of type parameter names. The type parameters can then be used in the body of the class declarations to define the members of the class. In the following example, the type parameters of Pair are TFirst and TSecond:

public class Pair{public TFirst First;public TSecond Second;}

A class type that is declared to take type parameters is called a generic class type. Struct, interface and delegate types can also be generic.

When the generic class is used, type arguments must be provided for each of the type parameters:

Pair pair = new Pair { First = 1, Second = two };int i = pair.First; // TFirst is intstring s = pair.Second; // TSecond is string

A generic type with type arguments provided, like Pair above, is called a constructed type.

Base classes

A class declaration may specify a base class by following the class name and type parameters with a colon and the name of the base class. Omitting a base class specification is the same as deriving from type object. In the following example, the base class of Point3D is Point, and the base class of Point is object:

public class Point{public int x, y;

public Point(int x, int y) {this.x = x;this.y = y;}}

public class Point3D: Point{public int z;

public Point3D(int x, int y, int z): base(x, y) {this.z = z;}}

A class inherits the members of its base class. Inheritance means that a class implicitly contains all members of its base class, except for the instance and static constructors, and the finalizers of the base class. A derived class can add new members to those it inherits, but it cannot remove the definition of an inherited member. In the previous example, Point3D inherits the x and y fields from Point, and every Point3D instance contains three fields, x, y, and z.

An implicit conversion exists from a class type to any of its base class types. Therefore, a variable of a class type can reference an instance of that class or an instance of any derived class. For example, given the previous class declarations, a variable of type Point can reference either a Point or a Point3D:

Point a = new Point(10, 20);Point b = new Point3D(10, 20, 30);

Fields

A field is a variable that is associated with a class or with an instance of a class.

A field declared with the static modifier defines a static field. A static field identifies exactly one storage location. No matter how many instances of a class are created, there is only ever one copy of a static field.

A field declared without the static modifier defines an instance field. Every instance of a class contains a separate copy of all the instance fields of that class.

In the following example, each instance of the Color class has a separate copy of ther, g, andb instance fields, but there is only one copy of the Black, White, Red, Green, and Blue static fields:

public class Color{public static readonly Color Black = new Color(0, 0, 0);public static readonly Color White = new Color(255, 255, 255);public static readonly Color Red = new Color(255, 0, 0);public static readonly Color Green = new Color(0, 255, 0);public static readonly Color Blue = new Color(0, 0, 255);

private byte r, g, b;

public Color(byte r, byte g, byte b) {this.r = r;this.g = g;this.b = b;}}

As shown in the previous example, read-only fields may be declared with a readonly modifier. Assignment to a readonly field can only occur as part of the fields declaration or in a constructor in the same class.

MethodsGeneral

A method is a member that implements a computation or action that can be performed by an object or class. Static methods are accessed through the class. Instance methods are accessed through instances of the class.

Methods have a (possibly empty) list of parameters, which represent values or variable references passed to the method, and a return type, which specifies the type of the value computed and returned by the method. A methods return type is void if it does not return a value.

Like types, methods may also have a set of type parameters, for which type arguments must be specified when the method is called. Unlike types, the type arguments can often be inferred from the arguments of a method call and need not be explicitly given.

The signature of a method must be unique in the class in which the method is declared. The signature of a method consists of the name of the method, the number of type parameters and the number, modifiers, and types of its parameters. The signature of a method does not include the return type.

Parameters

Parameters are used to pass values or variable references to methods. The parameters of a method get their actual values from the arguments that are specified when the method is invoked. There are four kinds of parameters: value parameters, reference parameters, output parameters, and parameter arrays.

A value parameter is used for input parameter passing. A value parameter corresponds to a local variable that gets its initial value from the argument that was passed for the parameter. Modifications to a value parameter do not affect the argument that was passed for the parameter.

Value parameters can be optional, by specifying a default value so that corresponding arguments can be omitted.

A reference parameter is used for both input and output parameter passing. The argument passed for a reference parameter must be a variable, and during execution of the method, the reference parameter represents the same storage location as the argument variable. A reference parameter is declared with the ref modifier. The following example shows the use of ref parameters.

using System;

class Test{static void Swap(ref int x, ref int y) {int temp = x;x = y;y = temp;}

static void Main() {int i = 1, j = 2;Swap(ref i, ref j);Console.WriteLine("{0} {1}", i, j);// Outputs "2 1"}}

An output parameter is used for output parameter passing. An output parameter is similar to a reference parameter except that the initial value of the caller-provided argument is unimportant. An output parameter is declared with the out modifier. The following example shows the use of out parameters.

using System;

class Test{static void Divide(int x, int y, out int result, out int remainder) {result = x / y;remainder = x % y;}

static void Main() {int res, rem;Divide(10, 3, out res, out rem);Console.WriteLine("{0} {1}", res, rem);// Outputs "3 1"}}

A parameter array permits a variable number of arguments to be passed to a method. A parameter array is declared with the params modifier. Only the last parameter of a method can be a parameter array, and the type of a parameter array must be a single-dimensional array type. The Write and WriteLine methods of the System.Console class are good examples of parameter array usage. They are declared as follows.

public class Console{public static void Write(string fmt, params object[] args) {}public static void WriteLine(string fmt, params object[] args) {}}

Within a method that uses a parameter array, the parameter array behaves exactly like a regular parameter of an array type. However, in an invocation of a method with a parameter array, it is possible to pass either a single argument of the parameter array type or any number of arguments of the element type of the parameter array. In the latter case, an array instance is automatically created and initialized with the given arguments. This example

Console.WriteLine("x={0} y={1} z={2}", x, y, z);

is equivalent to writing the following.

string s = "x={0} y={1} z={2}";object[] args = new object[3];args[0] = x;args[1] = y;args[2] = z;Console.WriteLine(s, args);

Method body and local variables

A methods body specifies the statements to execute when the method is invoked.

A method body can declare variables that are specific to the invocation of the method. Such variables are called local variables. A local variable declaration specifies a type name, a variable name, and possibly an initial value. The following example declares a local variablei with an initial value of zero and a local variablej with no initial value.

using System;

class Squares{static void Main() {int i = 0;int j;while (i < 10) {j = i * i;Console.WriteLine("{0} x {0} = {1}", i, j);i = i + 1;}}}

C# requires a local variable to be definitely assigned before its value can be obtained. For example, if the declaration of the previousi did not include an initial value, the compiler would report an error for the subsequent usages ofi becausei would not be definitely assigned at those points in the program.

A method can use return statements to return control to its caller. In a method returning void, return statements cannot specify an expression. In a method returning non-void, return statements must include an expression that computes the return value.

Static and instance methods

A method declared with a static modifier is a static method. A static method does not operate on a specific instance and can only directly access static members.

A method declared without a static modifier is an instance method. An instance method operates on a specific instance and can access both static and instance members. The instance on which an instance method was invoked can be explicitly accessed as this. It is an error to refer to this in a static method.

The following Entity class has both static and instance members.

class Entity{static int nextSerialNo;

int serialNo;

public Entity() {serialNo = nextSerialNo++;}

public int GetSerialNo() {return serialNo;}

public static int GetNextSerialNo() {return nextSerialNo;}

public static void SetNextSerialNo(int value) {nextSerialNo = value;}}

Each Entity instance contains a serial number (and presumably some other information that is not shown here). The Entity constructor (which is like an instance method) initializes the new instance with the next available serial number. Because the constructor is an instance member, it is permitted to access both the serialNo instance field and the nextSerialNo static field.

The GetNextSerialNo and SetNextSerialNo static methods can access the nextSerialNo static field, but it would be an error for them to directly access the serialNo instance field.

The following example shows the use of the Entity class.

using System;

class Test{static void Main() {Entity.SetNextSerialNo(1000);

Entity e1 = new Entity();Entity e2 = new Entity();

Console.WriteLine(e1.GetSerialNo());// Outputs "1000"Console.WriteLine(e2.GetSerialNo());// Outputs "1001"Console.WriteLine(Entity.GetNextSerialNo());// Outputs "1002"}}

Note that the SetNextSerialNo and GetNextSerialNo static methods are invoked on the class whereas the GetSerialNo instance method is invoked on instances of the class.

Virtual, override, and abstract methods

When an instance method declaration includes a virtual modifier, the method is said to be a virtual method. When no virtual modifier is present, the method is said to be a non-virtual method.

When a virtual method is invoked, the run-time type of the instance for which that invocation takes place determines the actual method implementation to invoke. In a nonvirtual method invocation, the compile-time type of the instance is the determining factor.

A virtual method can be overridden in a derived class. When an instance method declaration includes an override modifier, the method overrides an inherited virtual method with the same signature. Whereas a virtual method declaration introduces a new method, an override method declaration specializes an existing inherited virtual method by providing a new implementation of that method.

An abstract method is a virtual method with no implementation. An abstract method is declared with the abstract modifier and is permitted only in a class that is also declared abstract. An abstract method must be overridden in every non-abstract derived class.

The following example declares an abstract class, Expression, which represent