C# Annotated Standard

This document was uploaded by one of our users. The uploader already confirmed that they had the permission to publish it. If you are author/publisher or own the copyright of this documents, please report to us by using this DMCA report form.

Simply click on the Download Book button.

Yes, Book downloads on Ebookily are 100% Free.

Sometimes the book is free on Amazon As well, so go ahead and hit "Search on Amazon"

Standards, while being definitive, do not usually serve as the best reference to the use of a programming language. Books on languages usually are able to explain usage better, but lack the definitive precision of a standard. This book combines the two; it is the standard with added explanatory material. * Written by members of the standards committee * Annotates the standard with practical implementation advice * The definitive reference to the C# International Standard

Author(s): Jon Jagger; Nigel Perry; Peter Sestoft
Publisher: Morgan Kaufmann
Year: 2007

Language: English
Pages: 825

C# Annotated Standard
Copyright Page
Dedications
Contents
Foreword to the Annotated Standard
Preface to the Annotated Standard
Acknowledgments
About The Authors
Errata To The International Standard
The C# International Standard and Foreword
Introduction
CLI not required
Chapter 1: Scope
Chapter 2: Conformance
Interpreters
Chapter 3: Normative references
Chapter 4: Definitions
Application vs. program
Assembly vs. class files
Accessing class libraries
Programs, assemblies, applications and class libraries
Chapter 5: Notational conventions
Chapter 6: Acronyms and abbreviations
ASCII Rules!
The C# name
Chapter 7: General description
Where to look for requirements on unsafe constructs
Chapter 8: Language overview
Annotation free zone
8.1 Getting started
8.2 Types
8.2.1 Predefined types
8.2.2 Conversions
8.2.3 Array types
8.2.4 Type system unification
8.3 Variables and parameters
8.4 Automatic memory management
8.5 Expressions
8.6 Statements
8.7 Classes
8.7.1 Constants
8.7.2 Fields
8.7.3 Methods
8.7.4 Properties
8.7.5 Events
8.7.6 Operators
8.7.7 Indexers
8.7.8 Instance constructors
8.7.9 Finalizers
8.7.10 Static constructors
8.7.11 Inheritance
8.7.12 Static classes
8.7.13 Partial type declarations
8.8 Structs
8.9 Interfaces
8.10 Delegates
8.11 Enums
8.12 Namespaces and assemblies
8.13 Versioning
8.14 Extern aliases
8.15 Attributes
8.16 Generics
8.16.1 Why generics?
8.16.2 Creating and consuming generics
8.16.3 Multiple type parameters
8.16.4 Constraints
8.16.5 Generic methods
8.17 Anonymous methods
8.18 Iterators
8.19 Nullable types
Chapter 9: Lexical structure
9.1 Programs
Much ado about nothing
9.2 Grammars
9.2.1 Lexical grammar
9.2.2 Syntactic grammar
9.2.3 Grammar ambiguities
Rationale: the “following token” set
Similar cast expression ambiguity
F(G>7)
9.3 Lexical analysis
9.3.1 Line terminators
9.3.2 Comments
9.3.3 White space
9.4 Tokens
9.4.1 Unicode escape sequences
No escapes in verbatim strings
No escapes in comments
9.4.2 Identifiers
Identifier normalization
The humble underscore
Keyword escape mechanism
Code generation
9.4.3 Keywords
Language evolution
9.4.4 Literals
9.4.4.1 Boolean literals
Boolean arguments considered harmful?
9.4.4.2 Integer literals
Historical note
Boundary differences
9.4.4.3 Real literals
What is 1.D?
Money or deciMal?
9.4.4.4 Character literals
No octal character escapes
9.4.4.5 String literals
Platform independent newlines
Historical note
Happy birthday, Joel
Overspecification…
Hexadecimal escape character pitfalls
9.4.4.6 The null literal
9.4.5 Operators and punctuators
>>== tokenization oddity
Tokenization anecdote
9.5 Pre-processing directives
To pre-process, or not pre-process?
Why no delimited comments in #directives?
Why no macros?
9.5.1 Conditional compilation symbols
Conditional symbol oddity
No program-wide pre-processing symbols
9.5.2 Pre-processing expressions
Inequality is xor; equality is not-xor
9.5.3 Declaration directives
Rationale: pp-declaration placement
Conditional symbol style
9.5.4 Conditional compilation directives
Another issue with comments and #if
Carbuncle
9.5.5 Diagnostic directives
Diagnostic directive example
9.5.6 Region control
Historical note
9.5.7 Line directives
Historical note
#line example
9.5.8 Pragma directives
Chapter 10: Basic concepts
The emperor has no threads!
Example: Synchronization and Threads
10.1 Application startup
Main is callable
10.2 Application termination
Suppression of finalizers
No infanticide
10.3 Declarations
Declaration spaces and anonymous methods
10.4 Members
10.4.1 Namespace members
10.4.2 Struct members
10.4.3 Enumeration members
10.4.4 Class members
10.4.5 Interface members
10.4.7 Delegate members
10.5 Member access
10.5.1 Declared accessibility
Clarification of internal
Clarification of protected internal
Accessibility vs. visibility
Default considered harmful?
Default class accessibility pitfall
10.5.2 Accessibility domains
10.5.3 Protected access for instance members
Rationale: access to protected members
Access to other instantiations
Twin or just sibling?
10.5.4 Accessibility constraints
Declaration accessibility consistency
Constrained object creation
10.6 Signatures and overloading
Explicit interface implementation
Pitfall of overloading on ref or out
Why no ref and out overloading?
10.7 Scopes
Declaration scope within switch statements
Anonymous methods impact scope and lifetime
In scope but not referable
10.7.1 Name hiding
Context-sensitive name resolution
10.7.1.1 Hiding through nesting
Name hiding in a constructor
10.7.1.2 Hiding through inheritance
Abstract cannot be hidden
10.8 Namespace and type names
An extended example
10.8.1 Unqualified name
10.8.2 Fully qualified names
10.9 Automatic memory management
Constructors, exceptions, and finalizers: a volatile combination
One implementation’s garbage is another’s treasure
10.10 Execution order
Synchronous order, asynchronous chaos
Chapter 11: Types
Shallow copying of value types
Uniformity and hidden costs
11.1 Value types
The immediate base class of value types
11.1.1 The System.ValueType type
11.1.2 Default constructors
11.1.3 Struct types
11.1.4 Simple types
Use the keywords!
Keywords not allowed!
Do not use the keywords
11.1.5 Integral types
byte/sbyte naming oddity
11.1.6 Floating point types
Two’s company, three’s a crowd
The other floating point type
Rarity is relative
11.1.7 The decimal type
IEEE decimal
Using IEEE decimal in C#: supporting legacy data
11.1.8 The bool type
Strong Booleans
11.1.9 Enumeration types
Weak enums: distinct but similar
11.2 Reference types
Objects vs. values
11.2.1 Class types
11.2.2 The object type
11.2.3 The string type
Strings are immutable
Insecure strings
11.2.4 Interface types
Interface inheritance is not class inheritance
11.2.5 Array types
11.2.6 Delegate types
11.2.7 The null type
Pseudo-type
11.3 Boxing and unboxing
Can you tell whether a struct instance is boxed?
11.3.1 Boxing conversions
White lies and diaphanous types
11.3.2 Unboxing conversions
Sometimes your host bites…
11.4 Nullable types
11.4.1 Members
Default value
To be, or not to be…a value type
11.4.2 Implemented interfaces
Chapter 12: Variables
Aliasing
12.1 Variable categories
12.1.1 Static variables
12.1.2 Instance variables
12.1.2.1 Instance variables in classes
12.1.2.2 Instance variables in structs
12.1.3 Array elements
12.1.4 Value parameters
12.1.5 Reference parameters
Examples
Example: linked data structures
Example: avoiding repeated index calculations
Example: avoiding simple reassignment errors
12.1.6 Output parameters
Output parameters vs. reference parameters
Using output parameters to return multiple results
12.1.7 Local variables
Extended life or early death
12.2 Default values
Recursive initialization
Pointless instance field initialization
12.3 Definite assignment
Definitely assigned, maybe…
12.3.1 Initially assigned variables
12.3.2 Initially unassigned variables
12.3.3 Precise rules for determining definite assignment
Current compilers, constant expressions, and definite assignment
12.3.3.1 General rules for statements
Arriving from the unreachable
12.3.3.2 Block statements, checked, and unchecked statements
12.3.3.3 Expression statements
12.3.3.4 Declaration statements
12.3.3.5 If statements
Definitely confused?
12.3.3.6 Switch statements
12.3.3.7 While statements
12.3.3.8 Do statements
12.3.3.9 For statements
12.3.3.10 Break, continue, and goto statements
12.3.3.11 Throw statements
12.3.3.12 Return statements
12.3.3.13 Try-catch statements
12.3.3.14 Try-finally statements
12.3.3.15 Try-catch-finally statements
12.3.3.16 Foreach statements
12.3.3.17 Using statements
12.3.3.18 Lock statements
12.3.3.19 General rules for simple expressions
12.3.3.20 General rules for expressions with embedded expressions
12.3.3.21 Invocation expressions and object creation expressions
Trying to peek at an uninitialized variable
12.3.3.22 Simple assignment expressions
12.3.3.23 && expressions
12.3.3.24 || expressions
12.3.3.25 ! expressions
12.3.3.26 ?: expressions
12.3.3.27 Anonymous method expressions
12.3.3.28 Yield statements
12.3.3.29 ?? expressions
Alternative definite assignment rules for the ?? operator
12.4 Variable references
“classified as a variable”
12.5 Atomicity of variable references
Atomicity vs. volatility
Chapter 13: Conversions
13.1 Implicit conversions
13.1.1 Identity conversion
13.1.2 Implicit numeric conversions
Loss of precision
13.1.3 Implicit enumeration conversions
Equal rights for hexadecimals
13.1.4 Implicit reference conversions
Conversions to implemented interfaces
13.1.5 Boxing conversions
Leave my box alone…
13.1.6 Implicit type parameter conversions
13.1.7 Implicit constant expression conversions
Mind your constants
13.1.8 User-defined implicit conversions
13.2 Explicit conversions
Being explicitly implicit
13.2.1 Explicit numeric conversions
Why no double to decimal implicit conversions?
Decimal conversion exceptions dependent on format
13.2.2 Explicit enumeration conversions
Dubious explicit enum conversions
13.2.3 Explicit reference conversions
Never changes, maybe…
Conversion from System.Collections.Generic.IList
Mauled by the host, again…
13.2.4 Unboxing conversions
13.2.5 Explicit type parameter conversions
13.2.6 User-defined explicit conversions
13.3 Standard conversions
13.3.1 Standard implicit conversions
13.3.2 Standard explicit conversions
13.4 User-defined conversions
13.4.1 Permitted user-defined conversions
13.4.2 Evaluation of user-defined conversions
13.4.3 User-defined implicit conversions
13.4.4 User-defined explicit conversions
13.5 Anonymous method conversions
Anecdote: Mono widget design improves C#
13.6 Method group conversions
Non-orthogonality
Through a glass darkly…
13.7 Conversions involving nullable types
Wrapping conversions
13.7.1 Null type conversions
13.7.2 Nullable conversions
Nullable “identity” conversions
13.7.3 Lifted conversions
The same, but different
Chapter 14: Expressions
14.1 Expression classifications
14.1.1 Values of expressions
14.2 Operators
Operand order of evaluation
14.2.1 Operator precedence and associativity
Erratum and clarification
14.2.2 Operator overloading
14.2.3 Unary operator overload resolution
14.2.4 Binary operator overload resolution
14.2.5 Candidate user-defined operators
14.2.6 Numeric promotions
Land of surprises
Into the void
Loosely literal
Reasons for numeric promotion
14.2.6.1 Unary numeric promotions
14.2.6.2 Binary numeric promotions
14.2.7 Lifted operators
Null values in C# and in SQL
14.3 Member lookup
14.3.1 Base types
14.4 Function members
14.4.1 Argument lists
Unrealistic optimism
Hidden (small) costs of parameter arrays
String formatting not part of the Standard
14.4.2 Overload resolution
Overload resolution: C# vs. CIL
14.4.2.1 Applicable function member
14.4.2.2 Better function member
14.4.2.3 Better conversion
Lost digits
Better conversion pitfall
14.4.3 Function member invocation
No boxing
14.4.3.1 Invocations on boxed instances
From diaphanous to concrete
But wait, there is more…
14.5 Primary expressions
14.5.1 Literals
14.5.2 Simple names
14.5.2.1 Invariant meaning in blocks
Simpler confusion
14.5.3 Parenthesized expressions
14.5.4 Member access
14.5.4.1 Identical simple names and type names
14.5.5 Invocation expressions
14.5.5.1 Method invocations
What is not considered during overload resolution?
Sometimes there is no right answer…
14.5.5.2 Delegate invocations
Raising events and thread safety
14.5.6 Element access
14.5.6.1 Array access
Array indexing corner case
Red Katipo
14.5.6.2 Indexer access
14.5.7 This access
this = that?
14.5.8 Base access
Base access is nonvirtual
No override bypass
14.5.9 Postfix increment and decrement operators
Overflow eventually…
14.5.10 The new operator
New for old?
14.5.10.1 Object creation expressions
14.5.10.2 Array creation expressions
Java difference
14.5.10.3 Delegate creation expressions
Name equivalence and conversions
Creating a delegate from a delegate
Breaking change
14.5.11 The typeof operator
typeof(Generic<,>)
14.5.12 The sizeof operator
Marshal.SizeOf != sizeof
14.5.13 The checked and unchecked operators
Checked expression pitfall
(Un)checked constants
The meaning of (un)checked
14.5.14 Default value expression
Historical aside
14.5.15 Anonymous methods
Breaking the ties that bind…
Anonymous sharing
14.5.15.1 Anonymous method signatures
14.5.15.2 Anonymous method blocks
14.5.15.3 Outer variables
14.5.15.3.1 Captured outer variables
Captured local variables: modification and lifetime
Captured variable pitfall
Caution: space leaks
Visitor-style enumeration
14.5.15.3.2 Instantiation of local variables
Caution: local variables shared between threads
Caution: implementation-dependent space leaks
14.5.15.4 Anonymous method evaluation
Interlude: call-by-name
14.5.15.5 Implementation example
Anonymous methods, generic parameters, and a bug
14.6 Unary expressions
14.6.1 Unary plus operator
14.6.2 Unary minus operator
14.6.3 Logical negation operator
14.6.4 Bitwise complement operator
14.6.5 Prefix increment and decrement operators
Obscure C++ difference
14.6.6 Cast expressions
14.7 Arithmetic operators
Void arithmetic
Operator to instruction/method mapping not defined
14.7.1 Multiplication operator
14.7.2 Division operator
Divided we stand
A touch of Pentium
14.7.3 Remainder operator
Remainder latitude
IEC remainder
Further latitude
14.7.4 Addition operator
Hidden boxing
Implicitly avoiding the boxing
String concatenation efficiency
14.7.5 Subtraction operator
Negation, not negative
Legacy coding style
14.8 Shift operators
Negative shifts
Out of bounds shift count behavior?
Zero-extension signed shift
14.9 Relational and type-testing operators
Incomparable
All references are equal, but some are more equal than others
The invisible contract
Equality for all
Exploiting the built-in equality on value types
14.9.1 Integer comparison operators
14.9.2 Floating-point comparison operators
NaNs may be equal
14.9.3 Decimal comparison operators
14.9.4 Boolean equality operators
14.9.5 Enumeration comparison operators
14.9.6 Reference type equality operators
Specification mistake
Boxing not required
14.9.7 String equality operators
14.9.8 Delegate equality operators
Creating unique invocation list items
14.9.9 Equality operators and nullable types
14.9.10 is operator
14.9.11 as operator
is and as ignore user-defined conversions
14.10 Logical operators
14.10.1 Integer logical operators
Extra bits
Bit buckets
14.10.2 Enumeration logical operators
14.10.3 Boolean logical operators
Forgotten “long-circuiting” operators
14.10.4 The bool? logical operators
14.11 Conditional logical operators
14.11.1 Boolean conditional logical operators
14.11.2 User-defined conditional logical operators
true/false overloading
14.12 The null coalescing operator
Subtle interaction with implicit conversions
14.13 Conditional operator
14.14 Assignment operators
14.14.1 Simple assignment
14.14.2 Compound assignment
14.14.3 Event assignment
14.15 Expression
14.16 Constant expressions
Expressions can be constant
Compile time constant evaluation
Divide by zero always throws
14.17 Boolean expressions
Chapter 15: Statements
15.1 End points and reachability
Flow-analysis vs. unsigned types
15.2 Blocks
15.2.1 Statement lists
15.3 The empty statement
15.4 Labeled statements
15.5 Declaration statements
15.5.1 Local variable declarations
15.5.2 Local constant declarations
15.6 Expression statements
15.7 Selection statements
15.7.1 The if statement
15.7.2 The switch statement
Switching on a string
Switching on nullables…
Et tu, Mono?
Independent, within limits
Switch section reordering
Bad switch in a bad switch
15.8 Iteration statements
15.8.1 The while statement
15.8.2 The do statement
15.8.3 The for statement
Iteration count not fixed
15.8.4 The foreach statement
GetEnumerator() selection
Why is the iteration variable read-only?
Subtle change due to anonymous methods
Implications of MoveNext()
Iteration variable: read-only != readonly
15.9 Jump statements
15.9.1 The break statement
15.9.2 The continue statement
15.9.3 The goto statement
15.9.4 The return statement
15.9.5 The throw statement
null ! NullReferenceException
Plug-in style exception handling
Spot the difference
15.10 The try statement
Possible security vulnerability
Variety is the spice of life
Why is the exception variable name optional?
Rationale: Why is jumping out of a finally block forbidden?
Unstoppable exceptions?
Sometimes other code runs before finally
15.11 The checked and unchecked statements
Nested un/checking?
15.12 The lock statement
Lock thread safety?
Lock safety
15.13 The using statement
Rationale: designing for nonmemory resources
Redux: One implementation’s treasure is another’s garbage
15.14 The yield statement
yield syntax?
Chapter 16: Namespaces
16.1 Compilation units
Compilation-unit misnomer
Class libraries
16.2 Namespace declarations
16.3 Extern alias directives
Extern alias implied flexibility
16.4 Using directives
16.4.1 Using alias directives
Using alias constraints
Using alias reordering
16.4.2 Using namespace directives
Ouch, it bit me!
Intercepting calls
16.5 Namespace members
16.6 Type declarations
16.7 Qualified alias member
Chapter 17: Classes
17.1 Class declarations
Trailing semicolons
17.1.1 Class modifiers
17.1.1.1 Abstract classes
abstract + override == redundant?
abstract + override != redundant
17.1.1.2 Sealed classes
17.1.1.3 Static classes
Some bugs lead to features
17.1.2 Class base specification
Positional inheritance notation
17.1.2.1 Base classes
17.1.2.2 Interface implementations
17.1.3 Class body
17.1.4 Partial declarations
Divide and confuse…
But sometimes useful
17.2 Class members
Minor Java difference
17.2.1 Inheritance
17.2.2 The new modifier
17.2.3 Access modifiers
Absent modifier != default modifier
17.2.4 Constituent types
17.2.5 Static and instance members
No access to static members through instance expressions
Rationale: instance method call semantics
17.2.6 Nested types
Delegates and enums are types too
17.2.6.1 Fully qualified name
17.2.6.2 Declared accessibility
17.2.6.3 Hiding
17.2.6.4 this access
Simulating Java-style inner classes
17.2.6.5 Access to private and protected members of the containing type
Access clarification
Older C++ difference
17.2.7 Reserved member names
17.2.7.1 Member names reserved for properties
Neutral, but not agnostic
The meaning of “reserved”
17.2.7.2 Member names reserved for events
17.2.7.3 Member names reserved for indexers
Indexer names on CLI
17.2.7.4 Member names reserved for finalizers
17.3 Constants
Constant references do not trigger static initialization
Having nothing might be useful
17.4 Fields
17.4.1 Static and instance fields
17.4.2 Readonly fields
Readonly yet modifiable
17.4.2.1 Using static readonly fields for constants
17.4.2.2 Versioning of constants and static readonly fields
17.4.3 Volatile fields
Evolution of volatile
Unrealistic optimism redux
17.4.4 Field initialization
17.4.5 Variable initializers
17.4.5.1 Static field initialization
Static fields may never be initialized
17.4.5.2 Instance field initialization
Rationale: why field initializers cannot reference instance fields
Unable to create inner objects
17.5 Methods
Why no throw specifications?
17.5.1 Method parameters
17.5.1.1 Value parameters
17.5.1.2 Reference parameters
A round peg in a square hole…
17.5.1.3 Output parameters
17.5.1.4 Parameter arrays
Params arrays can be null
Is the params keyword needed?
17.5.2 Static and instance methods
17.5.3 Virtual methods
Instance methods are nonvirtual by default
Non-virtual calling of virtual methods
Invocation by compile-time and run-time type
17.5.4 Override methods
17.5.5 Sealed methods
17.5.6 Abstract methods
17.5.7 External methods
17.5.8 Method body
Foreign bodies
17.5.9 Method overloading
17.6 Properties
A property cannot be a ref or out parameter
The accessors of a property cannot be named
17.6.1 Static and instance properties
17.6.2 Accessors
More foreign bodies
Value hiding in an accessor
The most frequently requested new feature
17.6.3 Virtual, sealed, override, and abstract accessors
17.7 Events
Externally, events are write-only
17.7.1 Field-like events
Do-nothing delegate
Event –= vs. +=
Non-thread-safe struct events
17.7.2 Event accessors
Custom event handler semantics
17.7.3 Static and instance events
17.7.4 Virtual, sealed, override, and abstract accessors
17.8 Indexers
No static indexers
Named indexers
17.8.1 Indexer overloading
17.9 Operators
The best laid plans of mice and men…
Bedfellows: operators and structs
17.9.1 Unary operators
17.9.2 Binary operators
17.9.3 Conversion operators
Indirect implicit conversion to an interface
17.10 Instance constructors
17.10.1 Constructor initializers
Infinite recursion not erroneous
17.10.2 Instance variable initializers
17.10.3 Constructor execution
Rationale: field initialization before base constructor invocation
17.10.4 Default constructors
17.10.5 Private constructors
17.10.6 Optional instance constructor parameters
17.11 Static constructors
No access specifier; no parameter
Trigger one, trigger all
Constants are not “referenced”
Which static constructor is triggered?
Indeterminately deterministic
17.12 Finalizers
C++ destructors versus C# finalizers
Thwarting a finalizer
Thwarting a finalizer on the CLI
Finalizer issues
Final deadlock
Erroneous details
Chapter 18: Structs
Freedom of allocation
“Heap” allocation required
Union City blues
Premature optimization
Danger, UXB!
18.1 Struct declarations
18.1.1 Struct modifiers
18.1.2 Struct interfaces
18.1.3 Struct body
18.2 Struct members
18.3 Class and struct differences
readonly value-type fields
18.3.1 Value semantics
Struct layout cycles
Struct equality contracts
18.3.2 Inheritance
18.3.3 Assignment
18.3.4 Default values
Why do structs always have a default constructor?
18.3.5 Boxing and unboxing
18.3.6 Meaning of this
18.3.7 Field initializers
18.3.8 Constructors
Definite assignment inside a struct constructor
Non–dynamic allocation using new
18.3.9 Finalizers
Why no ~S() in struct type S?
18.3.10 Static constructors
Static constructor roulette
Chapter 19: Arrays
19.1 Array types
19.1.1 The System.Array type
19.2 Array creation
19.3 Array element access
foreach: simpler and faster
19.4 Array members
Arrays and vectors on the CLI
19.5 Array covariance
19.6 Arrays and the generic IList interface
19.7 Array initializers
Brace depth must equal array dimension
Chapter 20: Interfaces
20.1 Interface declarations
Partial interfaces?
20.1.1 Interface modifiers
20.1.2 Base interfaces
Different inheritance
20.1.3 Interface body
20.2 Interface members
20.2.1 Interface methods
20.2.2 Interface properties
20.2.3 Interface events
20.2.4 Interface indexers
20.2.5 Interface member access
20.3 Fully qualified interface member names
20.4 Interface implementations
Interfaces implemented through the base class
20.4.1 Explicit interface member implementations
Excess accessors not allowed in explicit interface member implementation
Simulating return type covariance
params oddity
20.4.2 Interface mapping
Morphing non-virtual methods
Inaccurate assertion
20.4.3 Interface implementation inheritance
Erratum?
Meaning of ‘‘implements’’
20.4.4 Interface re-implementation
Original implementation inaccessible
20.4.5 Abstract classes and interfaces
Abstract class interface alternatives
Chapter 21: Enums
Enums are integral
21.1 Enum declarations
Why no char underlying type?
21.2 Enum modifiers
21.3 Enum members
Second-class citizens
Type of an enum member
enum alternatives
21.4 The System.Enum type
21.5 Enum values and operations
Operations on enums
Chapter 22: Delegates
22.1 Delegate declarations
22.2 Delegate instantiation
Creation does not trigger static initialization
Delegates for value type instance methods
The C# pimpernel…
22.3 Delegate invocation
Chapter 23: Exceptions
Exceptions not advised as control flow
23.1 Causes of exceptions
Asynchronous exceptions
Unexpected exception
23.2 The System.Exception class
Optional InnerException
A good idea in theory, but not in practice
23.3 How exceptions are handled
Here be dragons
23.4 Common exception classes
Genteel exception classes?
Chapter 24: Attributes
24.1 Attribute classes
Suffix omission clarification
24.1.1 Attribute usage
24.1.2 Positional and named parameters
24.1.3 Attribute parameter types
24.2 Attribute specification
return vs. @return
Specification omission
Multiple declaration unclarity
24.3 Attribute instances
24.3.1 Compilation of an attribute
Constructor not called at compile-time
24.3.2 Run-time retrieval of an attribute instance
Reflection not part of C# standard
24.4 Reserved attributes
24.4.1 The AttributeUsage attribute
AttributeUsage and partial compile-time checks
24.4.2 The Conditional attribute
24.4.2.1 Conditional methods
Derived surprises
24.4.2.2 Conditional attribute classes
24.4.3 The Obsolete attribute
What error parameter?
Really obsolete
Chapter 25: Generics
Not separate, just pragmatic
C# generics compared to Ada, C++, Haskell, Java 1.5…
25.1 Generic class declarations
No type parameters in constructor declarations, but type arguments in constructor invocations
Overloading on number of type parameters
25.1.1 Type parameters
Null comparison despite no conversion
25.1.2 The instance type
25.1.3 Members of generic classes
25.1.4 Static fields in generic classes
Non-identical twins
25.1.5 Static constructors in generic classes
25.1.6 Accessing protected members
25.1.7 Overloading in generic classes
Clarifications
25.1.8 Parameter array methods and type parameters
25.1.9 Overriding and generic classes
25.1.10 Operators in generic classes
No operators on constructed type
Ignored ambiguity
25.1.11 Nested types in generic classes
Thinking generically: containers
25.2 Generic struct declarations
Infinite chains of constructed types
25.3 Generic interface declarations
25.3.1 Uniqueness of implemented interfaces
25.3.2 Explicit interface member implementations
25.4 Generic delegate declarations
Generic function types
25.5 Constructed types
25.5.1 Type arguments
25.5.2 Open and closed types
25.5.3 Base classes and interfaces of a constructed type
25.5.4 Members of a constructed type
25.5.5 Accessibility of a constructed type
25.5.6 Conversions
25.5.7 Using alias directives
Aliases do not take type parameters
25.6 Generic methods
25.6.1 Generic method signatures
25.6.2 Virtual generic methods
25.6.3 Calling generic methods
Polymorphic recursion
25.6.4 Inference of type arguments
Specification bug
Parameter arrays
Limited inference
25.6.5 Using a generic method with a delegate
From generic method to delegate
25.6.6 No generic properties, events, indexers, operators, constructors, or finalizers
Rationale: no generic constructors, operators, properties, or indexers
25.7 Constraints
No nullable constraint
Using constraints to simulate Java wildcard types
Ineffective base class?
No “numeric” constraints
25.7.1 Satisfying constraints
25.7.2 Member lookup on type parameters
25.7.3 Type parameters and boxing
No cast, no box
Inherited constraints
25.7.4 Conversions involving type parameters
Thinking generically: algorithms
Chapter 26: Iterators
Growing pains
Coroutines allowed?
26.1 Iterator blocks
26.1.1 Enumerator interfaces
26.1.2 Enumerable interfaces
26.1.3 Yield type
26.1.4 This access
How many iterators does it take to enumerate?
Enumerating a data structure: iterators, handwritten enumerator, or visitor style?
26.2 Enumerator objects
Iterators, finally, lock and using
Obscure iterator and finally/lock/using interaction
26.2.1 The MoveNext method
Implicit yield break at end of iterator block
26.2.2 The Current property
26.2.3 The Dispose method
26.3 Enumerable objects
26.3.1 The GetEnumerator method
26.4 Implementation example
Anecdote: iterator blocks, generic parameters, and a bug
Chapter 27: Unsafe code
27.1 Unsafe contexts
27.2 Pointer types
Missing grammar rule
Volatile pointers
A confusing C# vs. C/C++ syntax difference
27.3 Fixed and moveable variables
27.4 Pointer conversions
27.5 Pointers in expressions
27.5.1 Pointer indirection
27.5.2 Pointer member access
27.5.3 Pointer element access
27.5.4 The address-of operator
No pointer-to-volatile
27.5.5 Pointer increment and decrement
27.5.6 Pointer arithmetic
27.5.7 Pointer comparison
27.5.8 The sizeof operator
27.6 The fixed statement
27.7 Stack allocation
The programmer does not always come first
27.8 Dynamic memory allocation
A: Grammar
A.1 Lexical grammar
A.1.1 Line terminators
A.1.2 White space
A.1.3 Comments
A.1.4 Tokens
A.1.5 Unicode escape sequences
A.1.6 Identifiers
A.1.7 Keywords
A.1.8 Literals
A.1.9 Operators and punctuators
A.1.10 Pre-processing directives
A.2 Syntactic grammar
A.2.1 Basic concepts
A.2.2 Types
A.2.3 Variables
A.2.4 Expressions
A.2.5 Statements
A.2.6 Classes
A.2.7 Structs
A.2.8 Arrays
A.2.9 Interfaces
A.2.10 Enums
A.2.11 Delegates
A.2.12 Attributes
A.2.13 Generics
A.3 Grammar extensions for unsafe code
B: Portability issues
B.1 Undefined behavior
B.2 Implementation-defined behavior
B.3 Unspecified behavior
B.4 Other Issues
C: Naming Guidelines
Naming guideline summary
D: Standard Library
E: Documentation Comments
E.1 Introduction
E.2 Recommended tags
E.2.1
E.2.2
E.2.3
E.2.4
E.2.5
E.2.6
E.2.7
E.2.8
E.2.9
E.2.10
E.2.11
E.2.12
E.2.13
E.2.14
E.2.15
E.2.16
E.2.17
E.3 Processing the documentation file
E.3.1 ID string format
E.3.2 ID string examples
E.4 An example
E.4.1 C# source code
E.4.2 Resulting XML
F: Bibliography
Index