c# language specification - ecma international shar…  · web viewthis international standard is...

841
C # Language Specification Working Draft WD3.10 May 20 2016

Upload: lelien

Post on 03-Feb-2018

214 views

Category:

Documents


0 download

TRANSCRIPT

C# Language Specification

C#

Language Specification

Working Draft WD3.10

May 20 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

7.1 General17

7.2 Hello world17

7.3 Program structure18

7.4 Types and variables20

7.5 Expressions22

7.6 Statements25

7.7 Classes and objects29

7.7.1 General29

7.7.2 Members30

7.7.3 Accessibility30

7.7.4 Type parameters31

7.7.5 Base classes31

7.7.6 Fields32

7.7.7 Methods32

7.7.7.1 General32

7.7.7.2 Parameters33

7.7.7.3 Method body and local variables34

7.7.7.4 Static and instance methods34

7.7.7.5 Virtual, override, and abstract methods35

7.7.7.6 Method overloading37

7.7.8 Other function members38

7.7.8.1 General38

7.7.8.2 Constructors39

7.7.8.3 Properties40

7.7.8.4 Indexers40

7.7.8.5 Events41

7.7.8.6 Operators41

7.7.8.7 Finalizers42

7.8 Structs42

7.9 Arrays43

7.10 Interfaces44

7.11 Enums46

7.12 Delegates47

7.13 Attributes48

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 Members83

9.4.1 General83

9.4.2 Namespace members83

9.4.3 Struct members84

9.4.4 Enumeration members84

9.4.5 Class members84

9.4.6 Interface members84

9.4.7 Array members85

9.4.8 Delegate members85

9.5 Member access85

9.5.1 General85

9.5.2 Declared accessibility85

9.5.3 Accessibility domains86

9.5.4 Protected access for instance members88

9.5.5 Accessibility constraints89

9.6 Signatures and overloading90

9.7 Scopes92

9.7.1 General92

9.7.2 Name hiding94

9.7.2.1 General94

9.7.2.2 Hiding through nesting94

9.7.2.3 Hiding through inheritance95

9.8 Namespace and type names96

9.8.1 General96

9.8.2 Fully qualified names99

9.9 Automatic memory management100

9.10 Execution order102

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 simple expressions135

11.4.4.22 General rules for expressions with embedded expressions135

11.4.4.23 Invocation expressions and object creation expressions136

11.4.4.24 Simple assignment expressions136

11.4.4.25 && 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 Anonymous functions139

11.5 Variable references141

11.6 Atomicity of variable references141

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 types162

12.7.4 Implementation example162

12.8 Method group conversions166

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 operators176

13.4.7 Numeric promotions177

13.4.7.1 General177

13.4.7.2 Unary numeric promotions177

13.4.7.3 Binary numeric promotions177

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 parameters184

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 types188

13.6.3.6 Dependence188

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 Fixing190

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 expressions192

13.6.4 Overload resolution193

13.6.4.1 General193

13.6.4.2 Applicable function member193

13.6.4.3 Better function member194

13.6.4.4 Better conversion from expression196

13.6.4.5 Better conversion from type196

13.6.4.6 Better conversion target197

13.6.4.7 Overloading in generic classes197

13.6.5 Compile-time checking of dynamic overload resolution197

13.6.6 Function member invocation198

13.6.6.1 General198

13.6.6.2 Invocations on boxed instances199

13.7 Primary expressions200

13.7.1 General200

13.7.2 Literals200

13.7.3 Simple names201

13.7.3.1 General201

13.7.3.2 Invariant meaning in blocks202

13.7.4 Parenthesized expressions203

13.7.5 Member access203

13.7.5.1 General203

13.7.5.2 Identical simple names and type names205

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 invocations210

13.7.7 Element access211

13.7.7.1 General211

13.7.7.2 Array access211

13.7.7.3 Indexer access212

13.7.8 This access212

13.7.9 Base access213

13.7.10 Postfix increment and decrement operators214

13.7.11 The new operator215

13.7.11.1 General215

13.7.11.2 Object creation expressions216

13.7.11.3 Object initializers217

13.7.11.4 Collection initializers219

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 operator227

13.7.13 The checked and unchecked operators230

13.7.14 Default value expressions232

13.7.15 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 operator263

13.12 Logical operators265

13.12.1 General265

13.12.2 Integer logical operators265

13.12.3 Enumeration logical operators266

13.12.4 Boolean logical operators266

13.12.5 Nullable Boolean & and | operators266

13.13 Conditional logical operators267

13.13.1 General267

13.13.2 Boolean conditional logical operators268

13.13.3 User-defined conditional logical operators268

13.14 The null coalescing operator269

13.15 Conditional operator269

13.16 Anonymous function expressions270

13.16.1 General270

13.16.2 Anonymous function signatures272

13.16.3 Anonymous function bodies273

13.16.4 Overload resolution273

13.16.5 Anonymous functions and dynamic binding274

13.16.6 Outer variables274

13.16.6.1 General274

13.16.6.2 Captured outer variables274

13.16.6.3 Instantiation of local variables275

13.16.7 Evaluation of anonymous function expressions277

13.17 Query expressions277

13.17.1 General277

13.17.2 Ambiguities in query expressions278

13.17.3 Query expression translation279

13.17.3.1 General279

13.17.3.2 Select and groupby clauses with continuations279

13.17.3.3 Explicit range variable types280

13.17.3.4 Degenerate query expressions280

13.17.3.5 From, let, where, join and orderby clauses281

13.17.3.6 Select clauses284

13.17.3.7 Groupby clauses284

13.17.3.8 Transparent identifiers285

13.17.4 The query expression pattern286

13.18 Assignment operators287

13.18.1 General287

13.18.2 Simple assignment288

13.18.3 Compound assignment290

13.18.4 Event assignment291

13.19 Expression291

13.20 Constant expressions291

13.21 Boolean expressions292

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 statement319

14.14 The using statement320

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 directives334

15.6 Namespace member declarations336

15.7 Type declarations336

15.8 Qualified alias member337

15.8.1 General337

15.8.2 Uniqueness of aliases339

16. Classes341

16.1 General341

16.2 Class declarations341

16.2.1 General341

16.2.2 Class modifiers341

16.2.2.1 General341

16.2.2.2 Abstract classes342

16.2.2.3 Sealed classes342

16.2.2.4 Static classes343

16.2.3 Partial modifier344

16.2.4 Type parameters344

16.2.5 Class base specification344

16.2.5.1 General344

16.2.5.2 Base classes345

16.2.5.3 Interface implementations347

16.2.6 Type parameter constraints347

16.2.7 Class body352

16.3 Partial types353

16.3.1 General353

16.3.2 Attributes353

16.3.3 Modifiers354

16.3.4 Type parameters and constraints354

16.3.5 Base class355

16.3.6 Base interfaces355

16.3.7 Members355

16.3.8 Partial methods356

16.3.9 Name binding358

16.3.10 Field initialization359

16.4 Class members359

16.4.1 General359

16.4.2 The instance type360

16.4.3 Members of constructed types361

16.4.4 Inheritance362

16.4.5 The new modifier363

16.4.6 Access modifiers363

16.4.7 Constituent types364

16.4.8 Static and instance members364

16.4.9 Nested types365

16.4.9.1 General365

16.4.9.2 Fully qualified name365

16.4.9.3 Declared accessibility365

16.4.9.4 Hiding366

16.4.9.5 this access366

16.4.9.6 Access to private and protected members of the containing type367

16.4.9.7 Nested types in generic classes368

16.4.10 Reserved member names369

16.4.10.1 General369

16.4.10.2 Member names reserved for properties369

16.4.10.3 Member names reserved for events370

16.4.10.4 Member names reserved for indexers370

16.4.10.5 Member names reserved for finalizers370

16.5 Constants370

16.6 Fields372

16.6.1 General372

16.6.2 Static and instance fields373

16.6.3 Readonly fields373

16.6.3.1 General373

16.6.3.2 Using static readonly fields for constants374

16.6.3.3 Versioning of constants and static readonly fields374

16.6.4 Volatile fields375

16.6.5 Field initialization376

16.6.6 Variable initializers376

16.6.6.1 General376

16.6.6.2 Static field initialization377

16.6.6.3 Instance field initialization379

16.7 Methods379

16.7.1 General379

16.7.2 Method parameters381

16.7.2.1 General381

16.7.2.2 Value parameters383

16.7.2.3 Reference parameters383

16.7.2.4 Output parameters384

16.7.2.5 Parameter arrays385

16.7.3 Static and instance methods387

16.7.4 Virtual methods387

16.7.5 Override methods389

16.7.6 Sealed methods391

16.7.7 Abstract methods392

16.7.8 External methods393

16.7.9 Partial methods394

16.7.10 Extension methods394

16.7.11 Method body395

16.8 Properties396

16.8.1 General396

16.8.2 Static and instance properties397

16.8.3 Accessors397

16.8.4 Automatically implemented properties402

16.8.5 Accessibility403

16.8.6 Virtual, sealed, override, and abstract accessors404

16.9 Events406

16.9.1 General406

16.9.2 Field-like events408

16.9.3 Event accessors412

16.9.4 Static and instance events413

16.9.5 Virtual, sealed, override, and abstract accessors413

16.10 Indexers414

16.11 Operators417

16.11.1 General417

16.11.2 Unary operators418

16.11.3 Binary operators419

16.11.4 Conversion operators420

16.12 Instance constructors422

16.12.1 General422

16.12.2 Constructor initializers423

16.12.3 Instance variable initializers424

16.12.4 Constructor execution424

16.12.5 Default constructors426

16.13 Static constructors427

16.14 Finalizers429

16.15 Iterators431

16.15.1 General431

16.15.2 Enumerator interfaces431

16.15.3 Enumerable interfaces431

16.15.4 Yield type432

16.15.5 Enumerator objects432

16.15.5.1 General432

16.15.5.2 The MoveNext method432

16.15.5.3 The Current property433

16.15.5.4 The Dispose method434

16.15.6 Enumerable objects434

16.15.6.1 General434

16.15.6.2 The GetEnumerator method434

16.16 Async Functions441

16.16.1 General441

16.16.2 Evaluation of a task-returning async function441

16.16.3 Evaluation of a void-returning async function442

17. Structs443

17.1 General443

17.2 Struct declarations443

17.2.1 General443

17.2.2 Struct modifiers443

17.2.3 Partial modifier444

17.2.4 Struct interfaces444

17.2.5 Struct body444

17.3 Struct members444

17.4 Class and struct differences445

17.4.1 General445

17.4.2 Value semantics445

17.4.3 Inheritance446

17.4.4 Assignment446

17.4.5 Default values446

17.4.6 Boxing and unboxing447

17.4.7 Meaning of this448

17.4.8 Field initializers449

17.4.9 Constructors449

17.4.10 Static constructors450

17.4.11 Automatically implemented properties450

18. Arrays455

18.1 General455

18.2 Array types455

18.2.1 General455

18.2.2 The System.Array type456

18.2.3 Arrays and the generic IList interface456

18.3 Array creation457

18.4 Array element access457

18.5 Array members457

18.6 Array covariance457

18.7 Array initializers458

19. Interfaces461

19.1 General461

19.2 Interface declarations461

19.2.1 General461

19.2.2 Interface modifiers461

19.2.3 Partial modifier462

19.2.4 Variant type parameter lists462

19.2.4.1 General462

19.2.4.2 Variance safety462

19.2.4.3 Variance conversion463

19.2.5 Base interfaces463

19.3 Interface body464

19.4 Interface members464

19.4.1 General464

19.4.2 Interface methods465

19.4.3 Interface properties466

19.4.4 Interface events466

19.4.5 Interface indexers467

19.4.6 Interface member access467

19.5 Fully qualified interface member names469

19.6 Interface implementations469

19.6.1 General469

19.6.2 Explicit interface member implementations470

19.6.3 Uniqueness of implemented interfaces473

19.6.4 Implementation of generic methods474

19.6.5 Interface mapping474

19.6.6 Interface implementation inheritance477

19.6.7 Interface re-implementation479

19.6.8 Abstract classes and interfaces480

20. Enums481

20.1 General481

20.2 Enum declarations481

20.3 Enum modifiers481

20.4 Enum members482

20.5 The System.Enum type484

20.6 Enum values and operations484

21. Delegates485

21.1 General485

21.2 Delegate declarations485

21.3 Delegate compatibility488

21.4 Delegate instantiation488

21.5 Delegate invocation488

22. Exceptions491

22.1 General491

22.2 Causes of exceptions491

22.3 The System.Exception class491

22.4 How exceptions are handled492

22.5 Common exception classes492

23. Attributes495

23.1 General495

23.2 Attribute classes495

23.2.1 General495

23.2.2 Attribute usage495

23.2.3 Positional and named parameters497

23.2.4 Attribute parameter types497

23.3 Attribute specification498

23.4 Attribute instances505

23.4.1 General505

23.4.2 Compilation of an attribute505

23.4.3 Run-time retrieval of an attribute instance505

23.5 Reserved attributes506

23.5.1 General506

23.5.2 The AttributeUsage attribute507

23.5.3 The Conditional attribute507

23.5.3.1 General507

23.5.3.2 Conditional methods508

23.5.3.3 Conditional attribute classes510

23.5.4 The Obsolete attribute511

23.5.5 Caller-info attributes512

23.5.5.1 General512

23.5.5.2 The CallerLineNumber attribute513

23.5.5.3 The CallerFilePath attribute513

23.5.5.4 The CallerMemberName attribute514

23.6 Attributes for interoperation515

23.6.1 Interoperation with libraries515

23.6.2 Interoperation with other languages515

24. Unsafe code559

24.1 General559

24.2 Unsafe contexts559

24.3 Pointer types562

24.4 Fixed and moveable variables564

24.5 Pointer conversions565

24.5.1 General565

24.5.2 Pointer arrays566

24.6 Pointers in expressions567

24.6.1 General567

24.6.2 Pointer indirection567

24.6.3 Pointer member access568

24.6.4 Pointer element access569

24.6.5 The address-of operator569

24.6.6 Pointer increment and decrement570

24.6.7 Pointer arithmetic571

24.6.8 Pointer comparison571

24.6.9 The sizeof operator572

24.7 The fixed statement572

24.8 Fixed-size buffers576

24.8.1 General576

24.8.2 Fixed-size buffer declarations576

24.8.3 Fixed-size buffers in expressions577

24.8.4 Definite assignment checking578

24.9 Stack allocation578

24.10 Dynamic memory allocation579

Annex A. Grammar583

A.1 General583

A.2 Lexical grammar583

A.2.1 Comments584

A.2.2 Tokens584

A.2.3 Keywords586

A.2.4 Operators and punctuators588

A.2.5 Pre-processing directives588

A.3 Syntactic grammar591

A.3.1 Basic concepts591

A.3.2 Types591

A.3.3 Variables592

A.3.4 Expressions593

A.3.5 Statements599

A.3.6 Namespaces602

A.3.7 Classes603

A.3.8 Structs609

A.3.9 Arrays609

A.3.10 Interfaces610

A.3.11 Enums611

A.3.12 Delegates612

A.3.13 Attributes612

A.4 Grammar extensions for unsafe code613

Annex B. Portability issues617

B.1 General617

B.2 Undefined behavior617

B.3 Implementation-defined behavior617

B.4 Unspecified behavior618

B.5 Other Issues619

Annex C. Naming guidelines621

Annex D. Standard library623

Annex E. Documentation comments633

E.1 General633

E.2 Introduction633

E.3 Recommended tags634

E.3.1 General634

E.3.2 635

E.3.3 635

E.3.4 636

E.3.5 636

E.3.6 636

E.3.7 637

E.3.8 638

E.3.9 639

E.3.10 639

E.3.11 639

E.3.12 640

E.3.13 640

E.3.14 641

E.3.15 641

E.3.16 641

E.3.17 642

E.3.18 642

E.3.19 642

E.4 Processing the documentation file643

E.4.1 General643

E.4.2 ID string format643

E.4.3 ID string examples644

E.5 An example648

E.5.1 C# source code648

E.5.2 Resulting XML650

Annex F. Bibliography653

ECMA-334

Table of Contents

506

505

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 D).

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.

15 Namespaces

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 D. 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 unreachable 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 value 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 value 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 value types also do not have to be declared before they can be used. For each non-nullable value typeT there is a corresponding nullable value 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 a compatible 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 (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 (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 (13.9)

x * y

Multiplication

x / y

Division

x % y

Remainder

Additive (13.9)

x + y

Addition, string concatenation, delegate combination

x y

Subtraction, delegate removal

Shift (13.10)

x > y

Shift right

Relational and type testing (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 (13.11)

x == y

Equal

x != y

Not equal

Logical AND (13.12)

x & y

Integer bitwise AND, boolean logical AND

Logical XOR (13.12)

x ^ y

Integer bitwise XOR, boolean logical XOR

Logical OR (13.12)

x | y

Integer bitwise OR, boolean logical OR

Conditional AND (13.13)

x && y

Evaluatesy only ifx is true

Conditional OR (13.13)

x || y

Evaluatesy only ifx is false

Null coalescing (13.14)

X ?? y

Evaluates toy ifx is null, tox otherwise

Conditional (13.15)

x ? y : z

Evaluatesy ifx is true, z ifx is false

Assignment (13.18) or anonymous function (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;

private readonly object sync = new object();

public void Withdraw(decimal amount) {lock (thissync) {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 reachablein 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 metho