Chapter 15 Csharp 8 And Beyond
2 min read- Chapter 15 Csharp 8 And Beyond
- TL;DR
- How it works
- 15.2 Switch expressions
- 15.3 Recursive pattern matching
- 15.3.1 Property patterns
- 15.3.2 Deconstruction patterns
- 15.3.3 Omitting types
- 15.4 Indexes and ranges
- 15.5 More async integration
- 15.5.1 Async disposal (`await using`)
- 15.5.2 Async iteration (`await foreach`)
- 15.5.3 Async iterators
- 15.6 Features not yet in preview (book context)
- 15.7 Getting involved
- See also
- 15.1.1 What problem do they solve?
- 15.1.2 Changing meaning for reference types
- 15.1.3 Enter NRT (compiler-assisted contracts)
- 15.1.4 Compile time vs runtime
- 15.1.5 The “damn it” / bang operator (`!`)
- 15.1.6 Migration experience
Chapter 15 Csharp 8 And Beyond
TL;DR
Purpose of this chapter: understand the C# 8 feature set (and nearby future items) that meaningfully change how we write safe, expressive code: nullable reference types, switch expressions and richer patterns, ranges/indexes, and deeper async integration.
How it works
15.2 Switch expressions
Switch expressions make mapping logic concise and expression-oriented:
- Great for “value in → value out” mappings.
Guideline:
- Use when it improves clarity; don’t cram complex logic into a single expression if a statement-based switch is clearer.
15.3 Recursive pattern matching
Patterns can match deeper structure, not just top-level types.
15.3.1 Property patterns
Match based on property values (shape + constraints).
15.3.2 Deconstruction patterns
Match using Deconstruct shape.
15.3.3 Omitting types
Patterns can often infer types; use when it stays readable.
15.4 Indexes and ranges
Indexes/ranges make slicing more expressive:
^1means “from the end”.a[1..^1]means a slice/range (excluding endpoints based on indices).
Guideline:
- Great for parsing and data processing, but keep boundaries clear and test off-by-one behavior.
15.5 More async integration
15.5.1 Async disposal (await using)
Use for resources requiring async cleanup:
- Important for I/O resources where disposal can be asynchronous.
15.5.2 Async iteration (await foreach)
Consume IAsyncEnumerable<T> streams without buffering everything in memory.
15.5.3 Async iterators
Produce async streams with async + yield return semantics (conceptually).
Interview angle:
- These matter in high-throughput services for streaming data pipelines and backpressure-aware designs.
15.6 Features not yet in preview (book context)
The book discusses items that became real later (or evolved), e.g.:
- Default interface methods
- Records
Takeaway:
- Know the “direction of travel”: safer types, richer patterns, and better async ergonomics.
15.7 Getting involved
Practical suggestion:
- Track language proposals and adopt features deliberately; avoid churn without a payoff.
See also
Nullable reference types are about making nullability explicit in the type system so the compiler can warn about null mistakes.
15.1.1 What problem do they solve?
They reduce:
- NullReferenceExceptions in production.
- “Maybe null” ambiguity in APIs.
15.1.2 Changing meaning for reference types
With NRT enabled:
stringtypically means “non-null string”.string?means “may be null”.
15.1.3 Enter NRT (compiler-assisted contracts)
The compiler tracks null-state flow:
- It warns when you might dereference null.
- It warns when you assign a maybe-null to a non-nullable reference.
15.1.4 Compile time vs runtime
Important: NRT is primarily a compile-time feature.
- It doesn’t change runtime behavior of references (null still exists).
15.1.5 The “damn it” / bang operator (!)
x! means “I assert this isn’t null”.
Guideline:
- Use sparingly; treat it as a localized escape hatch when you can prove invariants but the compiler can’t.
15.1.6 Migration experience
Practical approach:
- Enable NRT in a controlled way, fix warnings in layers, add annotations to public APIs, and keep warning counts trending down.