📄 Page
1
Joseph Albahari C# 12 in a Nutshell The Definitive Reference
📄 Page
2
C# C# 12 in a Nutshell When you have questions about C# 12 or .NET 8, this best-selling guide has the answers you need. C# is a language of unusual flexibility and breadth, and with its continual growth, there’s always so much more to learn. In the tradition of O’Reilly’s Nutshell guides, this thoroughly updated edition is simply the best one-volume reference to the C# language available today. Aimed at intermediate and advanced programmers, this is a book whose explanations get straight to the point, covering C#, the CLR, and the core .NET libraries in depth without long intros or bloated samples. • Get up to speed on C# from syntax and variables to advanced topics such as pointers, closures, and patterns • Dig deep into LINQ, with three chapters dedicated to the topic • Explore concurrency and asynchrony, advanced threading, and parallel programming • Work with .NET features including regular expressions, networking, assemblies, spans, cryptography, and reflection.emit Joe Albahari, inventor of LINQPad, is the author of C# 10 in a Nutshell and C# 12 Pocket Reference. “C# 12 in a Nutshell is one of the few books I keep on my desk as a quick reference.” —Scott Guthrie Microsoft “Novices and experts alike will find the latest techniques in C# programming here.” —Eric Lippert C# Standards Committee Twitter: @oreillymedia linkedin.com/company/oreilly-media youtube.com/oreillymedia 9 7 8 1 0 9 8 1 4 7 4 4 0 5 6 9 9 9 US $69.99 CAN $87.99 ISBN: 978-1-098-14744-0
📄 Page
3
C# 12 IN A NUTSHELL The Definitive Reference Joseph Albahari
📄 Page
4
978-1-098-14744-0 [LSI] C# 12 in a Nutshell by Joseph Albahari Copyright © 2024 Joseph Albahari. All rights reserved. Printed in the United States of America. Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472. O’Reilly books may be purchased for educational, business, or sales promotional use. Online editions are also available for most titles (http://oreilly.com). For more information, contact our corporate/institutional sales department: 800-998-9938 or corporate@oreilly.com. Acquisitions Editor: Brian Guerin Development Editor: Corbin Collins Production Editor: Kristen Brown Copyeditor: Charles Roumeliotis Proofreader: Piper Editorial Consulting, LLC Indexer: WordCo Indexing Services, Inc. Interior Designer: David Futato Cover Designer: Karen Montgomery Illustrator: Kate Dullea December 2023: First Edition Revision History for the First Edition 2023-11-14: First Release See http://oreilly.com/catalog/errata.csp?isbn=9781098147440 for release details. The O’Reilly logo is a registered trademark of O’Reilly Media, Inc. C# 12 in a Nutshell, the cover image, and related trade dress are trademarks of O’Reilly Media, Inc. The views expressed in this work are those of the author, and do not represent the publish‐ er’s views. While the publisher and the author have used good faith efforts to ensure that the information and instructions contained in this work are accurate, the publisher and the author disclaim all responsibility for errors or omissions, including without limitation responsibility for damages resulting from the use of or reliance on this work. Use of the information and instructions contained in this work is at your own risk. If any code samples or other technology this work contains or describes is subject to open source licenses or the intellectual property rights of others, it is your responsibility to ensure that your use thereof complies with such licenses and/or rights.
📄 Page
5
Table of Contents Preface. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xi 1. Introducing C# and .NET. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 Object Orientation 1 Type Safety 2 Memory Management 3 Platform Support 3 CLRs, BCLs, and Runtimes 3 A Brief History of C# 8 2. C# Language Basics. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 A First C# Program 31 Syntax 34 Type Basics 36 Numeric Types 47 Boolean Type and Operators 55 Strings and Characters 57 Arrays 61 Variables and Parameters 67 Expressions and Operators 78 Null Operators 82 Statements 84 Namespaces 95 3. Creating Types in C#. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 Classes 103 Inheritance 126 The object Type 138 Structs 142 iii
📄 Page
6
Access Modifiers 145 Interfaces 147 Enums 154 Nested Types 157 Generics 159 4. Advanced C#. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173 Delegates 173 Events 181 Lambda Expressions 188 Anonymous Methods 194 try Statements and Exceptions 195 Enumeration and Iterators 203 Nullable Value Types 210 Nullable Reference Types 215 Extension Methods 217 Anonymous Types 220 Tuples 222 Records 227 Patterns 238 Attributes 243 Caller Info Attributes 246 Dynamic Binding 248 Operator Overloading 256 Static Polymorphism 260 Unsafe Code and Pointers 263 Preprocessor Directives 270 XML Documentation 272 5. .NET Overview. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277 Runtime Targets and TFMs 279 .NET Standard 279 Reference Assemblies 281 Runtime and C# Language Versions 281 The CLR and BCL 281 Application Layers 286 6. .NET Fundamentals. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291 String and Text Handling 291 Dates and Times 304 iv | Table of Contents
📄 Page
7
Dates and Time Zones 312 Formatting and Parsing 317 Standard Format Strings and Parsing Flags 323 Other Conversion Mechanisms 330 Globalization 334 Working with Numbers 335 Enums 340 The Guid Struct 344 Equality Comparison 344 Order Comparison 355 Utility Classes 358 7. Collections. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365 Enumeration 366 The ICollection and IList Interfaces 373 The Array Class 377 Lists, Queues, Stacks, and Sets 385 Dictionaries 394 Customizable Collections and Proxies 401 Immutable Collections 406 Frozen Collections 410 Plugging in Equality and Order 411 8. LINQ Queries. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 419 Getting Started 419 Fluent Syntax 421 Query Expressions 427 Deferred Execution 432 Subqueries 438 Composition Strategies 442 Projection Strategies 445 Interpreted Queries 448 EF Core 454 Building Query Expressions 466 9. LINQ Operators. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 471 Overview 472 Filtering 475 Projecting 480 Joining 492 Table of Contents | v
📄 Page
8
Ordering 500 Grouping 503 Set Operators 507 Conversion Methods 509 Element Operators 512 Aggregation Methods 514 Quantifiers 519 Generation Methods 520 10. LINQ to XML. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 521 Architectural Overview 521 X-DOM Overview 522 Instantiating an X-DOM 526 Navigating and Querying 528 Updating an X-DOM 534 Working with Values 537 Documents and Declarations 539 Names and Namespaces 543 Annotations 548 Projecting into an X-DOM 549 11. Other XML and JSON Technologies. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 553 XmlReader 553 XmlWriter 561 Patterns for Using XmlReader/XmlWriter 563 Working with JSON 568 12. Disposal and Garbage Collection. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 581 IDisposable, Dispose, and Close 581 Automatic Garbage Collection 587 Finalizers 589 How the GC Works 593 Managed Memory Leaks 600 Weak References 603 13. Diagnostics. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 607 Conditional Compilation 607 Debug and Trace Classes 611 Debugger Integration 614 Processes and Process Threads 615 vi | Table of Contents
📄 Page
9
StackTrace and StackFrame 616 Windows Event Logs 618 Performance Counters 620 The Stopwatch Class 624 Cross-Platform Diagnostic Tools 625 14. Concurrency and Asynchrony. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 631 Introduction 631 Threading 632 Tasks 648 Principles of Asynchrony 656 Asynchronous Functions in C# 661 Asynchronous Patterns 681 Obsolete Patterns 689 15. Streams and I/O. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 693 Stream Architecture 693 Using Streams 695 Stream Adapters 709 Compression Streams 718 Working with ZIP Files 721 Working with Tar Files 722 File and Directory Operations 723 OS Security 733 Memory-Mapped Files 736 16. Networking. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 741 Network Architecture 741 Addresses and Ports 743 URIs 744 HttpClient 746 Writing an HTTP Server 755 Using DNS 758 Sending Mail with SmtpClient 758 Using TCP 759 Receiving POP3 Mail with TCP 763 17. Assemblies. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 765 What’s in an Assembly 765 Strong Names and Assembly Signing 770 Table of Contents | vii
📄 Page
10
Assembly Names 771 Authenticode Signing 773 Resources and Satellite Assemblies 776 Loading, Resolving, and Isolating Assemblies 783 18. Reflection and Metadata. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 805 Reflecting and Activating Types 806 Reflecting and Invoking Members 813 Reflecting Assemblies 827 Working with Attributes 828 Dynamic Code Generation 834 Emitting Assemblies and Types 841 Emitting Type Members 844 Emitting Generic Methods and Types 849 Awkward Emission Targets 851 Parsing IL 855 19. Dynamic Programming. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 861 The Dynamic Language Runtime 861 Dynamic Member Overload Resolution 863 Implementing Dynamic Objects 869 Interoperating with Dynamic Languages 872 20. Cryptography. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 875 Overview 875 Windows Data Protection 876 Hashing 877 Symmetric Encryption 879 Public-Key Encryption and Signing 884 21. Advanced Threading. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 889 Synchronization Overview 890 Exclusive Locking 890 Locking and Thread Safety 898 Nonexclusive Locking 904 Signaling with Event Wait Handles 911 The Barrier Class 919 Lazy Initialization 920 Thread-Local Storage 923 Timers 926 viii | Table of Contents
📄 Page
11
22. Parallel Programming. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 931 Why PFX? 932 PLINQ 935 The Parallel Class 948 Task Parallelism 954 Working with AggregateException 964 Concurrent Collections 966 BlockingCollection<T> 969 23. Span<T> and Memory<T>. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 973 Spans and Slicing 974 Memory<T> 978 Forward-Only Enumerators 980 Working with Stack-Allocated and Unmanaged Memory 982 24. Native and COM Interoperability. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 985 Calling into Native DLLs 985 Type and Parameter Marshaling 986 Callbacks from Unmanaged Code 991 Simulating a C Union 994 Shared Memory 995 Mapping a Struct to Unmanaged Memory 997 COM Interoperability 1001 Calling a COM Component from C# 1003 Embedding Interop Types 1006 Exposing C# Objects to COM 1007 25. Regular Expressions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1011 Regular Expression Basics 1011 Quantifiers 1016 Zero-Width Assertions 1017 Groups 1020 Replacing and Splitting Text 1022 Cookbook Regular Expressions 1023 Regular Expressions Language Reference 1027 Index. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1031 Table of Contents | ix
📄 Page
12
(This page has no text content)
📄 Page
13
Preface C# 12 represents the ninth major update to Microsoft’s flagship programming language, positioning C# as a language with unusual flexibility and breadth. At one end, it offers high-level abstractions such as query expressions and asynchronous continuations, whereas at the other end, it allows low-level efficiency through con‐ structs such as custom value types and optional pointers. The price of this growth is that there’s more than ever to learn. Although tools such as Microsoft’s IntelliSense—and online references—are excellent in helping you on the job, they presume an existing map of conceptual knowledge. This book provides exactly that map of knowledge in a concise and unified style—free of clutter and long introductions. Like the past seven editions, C# 12 in a Nutshell is organized around concepts and use cases, making it friendly both to sequential reading and to random browsing. It also plumbs significant depths while assuming only basic background knowledge, making it accessible to intermediate as well as advanced readers. This book covers C#, the Common Language Runtime (CLR), and the .NET 8 Base Class Library (BCL). We’ve chosen this focus to allow space for difficult and advanced topics without compromising depth or readability. Features recently added to C# are flagged so that you can also use this book as a reference for C# 11 and C# 10. Intended Audience This book targets intermediate to advanced audiences. No prior knowledge of C# is required, but some general programming experience is necessary. For the beginner, this book complements, rather than replaces, a tutorial-style introduction to programming. xi
📄 Page
14
This book is an ideal companion to any of the vast array of books that focus on an applied technology such as ASP.NET Core or Windows Presentation Foundation (WPF). C# 12 in a Nutshell covers the areas of the language and .NET that such books omit, and vice versa. If you’re looking for a book that skims every .NET technology, this is not for you. This book is also unsuitable if you want to learn about APIs specific to mobile device development. How This Book Is Organized Chapter 2 through Chapter 4 concentrate purely on C#, starting with the basics of syntax, types, and variables, and finishing with advanced topics such as unsafe code and preprocessor directives. If you’re new to the language, you should read these chapters sequentially. The remaining chapters focus on .NET 8’s Base Class Libraries, covering such topics as Language-Integrated Query (LINQ), XML, collections, concurrency, I/O and networking, memory management, reflection, dynamic programming, attributes, cryptography, and native interoperability. You can read most of these chapters ran‐ domly, except for Chapters 5 and 6, which lay a foundation for subsequent topics. You’re also best off reading the three chapters on LINQ in sequence, and some chapters assume some knowledge of concurrency, which we cover in Chapter 14. What You Need to Use This Book The examples in this book require .NET 8. You will also find Microsoft’s .NET documentation useful to look up individual types and members (which is available online). Although it’s possible to write source code in a simple text editor and build your program from the command line, you’ll be much more productive with a code scratchpad for instantly testing code snippets, plus an integrated development envi‐ ronment (IDE) for producing executables and libraries. For a Windows code scratchpad, download LINQPad 8 from www.linqpad.net (free). LINQPad fully supports C# 12 and is maintained by the author. For a Windows IDE, download Visual Studio 2022: any edition is suitable for what’s taught in this book. For a cross-platform IDE, download Visual Studio Code. All code listings for all chapters are available as interactive (editable) LINQPad samples. You can download the entire lot in a single click: at the bottom left, click the LINQPad’s Samples tab, click “Download more samples,” and then choose “C# 12 in a Nutshell.” xii | Preface
📄 Page
15
Conventions Used in This Book The book uses basic UML notation to illustrate relationships between types, as shown in Figure P-1. A slanted rectangle means an abstract class; a circle means an interface. A line with a hollow triangle denotes inheritance, with the triangle pointing to the base type. A line with an arrow denotes a one-way association; a line without an arrow denotes a two-way association. Figure P-1. Sample diagram The following typographical conventions are used in this book: Italic Indicates new terms, URIs, filenames, and directories Constant width Indicates C# code, keywords and identifiers, and program output Constant width bold Shows a highlighted section of code Constant width italic Shows text that should be replaced with user-supplied values Preface | xiii
📄 Page
16
Using Code Examples Supplemental material (code examples, exercises, etc.) is available for download at http://www.albahari.com/nutshell. This book is here to help you get your job done. In general, you may use the code in this book in your programs and documentation. You do not need to contact us for permission unless you’re reproducing a significant portion of the code. For example, writing a program that uses several chunks of code from this book does not require permission. Selling or distributing examples from O’Reilly books does require permission. Answering a question by citing this book and quoting example code does not require permission (although we appreciate attribution). Incorporating a significant amount of example code from this book into your product’s documentation does require permission. We appreciate, but generally do not require, attribution. An attribution usually includes the title, author, publisher, and ISBN. For example: “C# 12 in a Nutshell by Joseph Albahari (O’Reilly). Copyright 2024 Joseph Albahari, 978-1-098-14744-0.” If you feel your use of code examples falls outside fair use or the permission given here, feel free to contact us at permissions@oreilly.com. How to Contact Us Please address comments and questions concerning this book to the publisher: O’Reilly Media, Inc. 1005 Gravenstein Highway North Sebastopol, CA 95472 800-889-8969 (in the United States or Canada) 707-829-7019 (international or local) 707-829-0104 (fax) support@oreilly.com https://www.oreilly.com/about/contact.html We have a web page for this book, where we list errata, examples, and any additional information. You can access this page at https://oreil.ly/c-sharp-nutshell-12. Code listings and additional resources are provided at: http://www.albahari.com/nutshell/ For news and information about our books and courses, visit https://oreilly.com. Find us on LinkedIn: https://linkedin.com/company/oreilly-media Follow us on Twitter: https://twitter.com/oreillymedia Watch us on YouTube: https://youtube.com/oreillymedia xiv | Preface
📄 Page
17
Acknowledgments Joseph Albahari Since its first incarnation in 2007, this book has relied on input from some superb technical reviewers. For their input into recent editions, I’d like to extend particular thanks to Stephen Toub, Paulo Morgado, Fred Silberberg, Vitek Karas, Aaron Rob‐ inson, Jan Vorlicek, Sam Gentile, Rod Stephens, Jared Parsons, Matthew Groves, Dixin Yan, Lee Coward, Bonnie DeWitt, Wonseok Chae, Lori Lalonde, and James Montemagno. And for their input into earlier editions, I’m most grateful to Eric Lippert, Jon Skeet, Stephen Toub, Nicholas Paldino, Chris Burrows, Shawn Farkas, Brian Grunkemeyer, Maoni Stephens, David DeWinter, Mike Barnett, Melitta Andersen, Mitch Wheat, Brian Peek, Krzysztof Cwalina, Matt Warren, Joel Pobar, Glyn Griffiths, Ion Vasi‐ lian, Brad Abrams, and Adam Nathan. I appreciate that many of the technical reviewers are accomplished individuals at Microsoft, and I particularly thank you for taking the time to raise this book to the next quality bar. I want to thank Ben Albahari and Eric Johannsen, who contributed to previous editions, and the O’Reilly team—particularly my efficient and responsive editor Corbin Collins. Finally, my deepest thanks to my wonderful wife, Li Albahari, whose presence kept me happy throughout the project. Preface | xv
📄 Page
18
(This page has no text content)
📄 Page
19
1 Introducing C# and .NET C# is a general-purpose, type-safe, object-oriented programming language. The goal of the language is programmer productivity. To this end, C# balances simplicity, expressiveness, and performance. The chief architect of the language since its first version is Anders Hejlsberg (creator of Turbo Pascal and architect of Delphi). The C# language is platform neutral and works with a range of platform-specific runtimes. Object Orientation C# is a rich implementation of the object-orientation paradigm, which includes encapsulation, inheritance, and polymorphism. Encapsulation means creating a boundary around an object to separate its external (public) behavior from its inter‐ nal (private) implementation details. Following are the distinctive features of C# from an object-oriented perspective: Unified type system The fundamental building block in C# is an encapsulated unit of data and func‐ tions called a type. C# has a unified type system in which all types ultimately share a common base type. This means that all types, whether they represent business objects or are primitive types such as numbers, share the same basic functionality. For example, an instance of any type can be converted to a string by calling its ToString method. Classes and interfaces In a traditional object-oriented paradigm, the only kind of type is a class. In C#, there are several other kinds of types, one of which is an interface. An interface is like a class that cannot hold data. This means that it can define only behavior (and not state), which allows for multiple inheritance as well as a separation between specification and implementation. 1
📄 Page
20
Properties, methods, and events In the pure object-oriented paradigm, all functions are methods. In C#, meth‐ ods are only one kind of function member, which also includes properties and events (there are others, too). Properties are function members that encapsulate a piece of an object’s state such as a button’s color or a label’s text. Events are function members that simplify acting on object state changes. Although C# is primarily an object-oriented language, it also borrows from the functional programming paradigm, specifically: Functions can be treated as values Using delegates, C# allows functions to be passed as values to and from other functions. C# supports patterns for purity Core to functional programming is avoiding the use of variables whose values change, in favor of declarative patterns. C# has key features to help with those patterns, including the ability to write unnamed functions on the fly that “capture” variables (lambda expressions), and the ability to perform list or reactive programming via query expressions. C# also provides records, which make it easy to write immutable (read-only) types. Type Safety C# is primarily a type-safe language, meaning that instances of types can interact only through protocols they define, thereby ensuring each type’s internal consis‐ tency. For instance, C# prevents you from interacting with a string type as though it were an integer type. More specifically, C# supports static typing, meaning that the language enforces type safety at compile time. This is in addition to type safety being enforced at runtime. Static typing eliminates a large class of errors before a program is even run. It shifts the burden away from runtime unit tests onto the compiler to verify that all the types in a program fit together correctly. This makes large programs much easier to manage, more predictable, and more robust. Furthermore, static typing allows tools such as IntelliSense in Visual Studio to help you write a program because it knows for a given variable what type it is, and hence what methods you can call on that variable. Such tools can also identify everywhere in your program that a variable, type, or method is used, allowing for reliable refactoring. C# also allows parts of your code to be dynamically typed via the dynamic keyword. However, C# remains a predominantly statically typed language. 2 | Chapter 1: Introducing C# and .NET