|
Foreword | xv |
| Introduction | xix |
| PART I LAYING THE GROUNDWORK | |
| 1 Fundamentals of Object-Oriented Programming | 3 |
| Everything Is an Object | 5 |
| Objects vs. Classes | 9 |
| Instantiation | 9 |
| The Three Tenets of Object-Oriented Programming Languages | 11 |
| Encapsulation | 11 |
| Inheritance | 14 |
| Polymorphism | 17 |
| 2 Introducing Microsoft .NET | 23 |
| The Microsoft .NET Platform | 23 |
| The .NET Framework | 24 |
| Windows DNA and .NET | 24 |
| The Common Language Runtime | 25 |
| The .NET Framework Class Libraries | 26 |
| Microsoft Intermediate Language and the JITters | 28 |
| Unified Type System | 30 |
| Metadata and Reflection | 30 |
| Security | 31 |
| Deployment | 32 |
| Interoperability with Unmanaged Code | 32 |
| 3 Hello, C# | 35 |
| Writing Your First C# Application | 35 |
| Choosing an Editor | 35 |
| "Hello, World" | 38 |
| Using the Command-Line Compiler | 38 |
| Running the Application | 39 |
| Code Walk-Through | 40 |
| One-Stop Programming | 40 |
| Classes and Members | 41 |
| The Main Method | 41 |
| The System.Console.WriteLine Method | 42 |
| Namespaces and the using Directive | 42 |
| Skeleton Code | 43 |
| Something Went Wrong! | 45 |
| Compile-Time Errors | 45 |
| Spelunking with ILDASM | 46 |
| "Hello, World" in MSIL | 47 |
| C# Programming Guidelines | 50 |
| When to Define Your Own Namespaces | 50 |
| Naming Guidelines | 50 |
| Naming Convention Standards | 51 |
| PART II C# CLASS FUNDAMENTALS | |
| 4 The Type System | 57 |
| Everything Is an Object | 57 |
| Value Types and Reference Types | 58 |
| Value Types | 58 |
| Reference Types | 59 |
| Boxing and Unboxing | 59 |
| The Root of All Types: System.Object | 60 |
| Types and Aliases | 61 |
| Casting Between Types | 62 |
| Namespaces | 64 |
| The using Keyword | 65 |
| CTS Benefits | 66 |
| Language Interoperability | 66 |
| Singly Rooted Object Hierarchy | 67 |
| Type Safety | 67 |
| 5 Classes | 69 |
| Defining Classes | 69 |
| Class Members | 70 |
| Access Modifiers | 71 |
| The Main Method | 72 |
| Command-Line Arguments | 73 |
| Return Values | 74 |
| Multiple Main Methods | 74 |
| Constructors | 75 |
| Static Members and Instance Members | 77 |
| Constructor Initializers | 79 |
| Constants vs. Read-Only Fields | 82 |
| Constants | 82 |
| Read-Only Fields | 83 |
| Object Cleanup and Resource Management | 85 |
| A Bit of History | 86 |
| Deterministic Finalization | 87 |
| Performance | 88 |
| The Perfect Solution | 94 |
| The (Almost) Perfect Solution | 95 |
| The Dispose Design Pattern | 96 |
| Inheritance | 97 |
| Multiple Interfaces | 99 |
| Sealed Classes | 100 |
| 6 Methods | 103 |
| ref and out Method Parameters | 103 |
| Method Overloading | 108 |
| Variable Method Parameters | 111 |
| Virtual Methods | 112 |
| Method Overriding | 112 |
| Polymorphism | 114 |
| Static Methods | 120 |
| Access to Class Members | 122 |
| 7 Properties, Arrays, and Indexers | 123 |
| Properties as Smart Fields | 123 |
| Defining and Using Properties | 124 |
| What the Compiler Is Really Doing | 126 |
| Read-Only Properties | 128 |
| Inheriting Properties | 128 |
| Advanced Use of Properties | 129 |
| Arrays | 130 |
| Declaring Arrays | 130 |
| Single-Dimensional Array Example | 131 |
| Multidimensional Arrays | 132 |
| Querying for Rank | 134 |
| Jagged Arrays | 135 |
| Treating Objects Like Arrays by Using Indexers | 136 |
| Defining Indexers | 137 |
| Indexer Example | 138 |
| Design Guidelines | 140 |
| 8 Attributes | 143 |
| Introducing Attributes | 144 |
| Defining Attributes | 145 |
| Querying About Attributes | 146 |
| Class Attributes | 146 |
| Method Attributes | 149 |
| Field Attributes | 151 |
| Attribute Parameters | 153 |
| Positional Parameters and Named Parameters | 153 |
| Common Mistakes with Named Parameters | 155 |
| Valid Attribute Parameter Types | 155 |
| The AttributeUsage Attribute | 156 |
| Defining an Attribute Target | 156 |
| Single-Use and Multiuse Attributes | 158 |
| Specifying Inheritance Attribute Rules | 159 |
| Attribute Identifiers | 159 |
| 9 Interfaces | 161 |
| Interface Use | 162 |
| Declaring Interfaces | 163 |
| Implementing Interfaces | 164 |
| Querying for Implementation by Using is | 166 |
| Querying for Implementation by Using as | 170 |
| Explicit Interface Member Name Qualification | 173 |
| Name Hiding with Interfaces | 173 |
| Avoiding Name Ambiguity | 176 |
| Interfaces and Inheritance | 180 |
| Combining Interfaces | 183 |
| PART III WRITING CODE | |
| 10 Expressions and Operators | 189 |
| Operators Defined | 189 |
| Operator Precedence | 190 |
| How C# Determines Precedence | 191 |
| Left and Right Associativity | 191 |
| Practical Usage | 192 |
| C# Operators | 193 |
| Primary Expression Operators | 193 |
| Mathematical Operators | 198 |
| Relational Operators | 206 |
| Simple Assignment Operators | 209 |
| 11 Program Flow Control | 215 |
| Selection Statements | 215 |
| The if Statement | 215 |
| The switch Statement | 220 |
| Iteration Statements | 225 |
| The while Statement | 225 |
| The do/while Statement | 227 |
| The for Statement | 229 |
| The foreach Statement | 232 |
| Branching with Jump Statements | 234 |
| The break Statement | 234 |
| The continue Statement | 237 |
| The Infamous goto Statement | 238 |
| The return Statement | 243 |
| 12 Error Handling with Exceptions | 245 |
| Overview of Exception Handling | 245 |
| Basic Exception-Handling Syntax | 247 |
| Throwing an Exception | 247 |
| Catching an Exception | 247 |
| Rethrowing an Exception | 248 |
| Cleaning Up with finally | 249 |
| Comparing Error-Handling Techniques | 250 |
| The Benefits of Exception Handling Over Return Codes | 251 |
| Handling Errors in the Correct Context | 253 |
| Improving Code Readability | 254 |
| Throwing Exceptions From Constructors | 256 |
| Using the System.Exception Class | 256 |
| Constructing an Exception Object | 256 |
| Using the StackTrace Property | 259 |
| Catching Multiple Exception Types | 260 |
| Deriving Your Own Exception Classes | 261 |
| Designing Your Code with Exception Handling | 263 |
| Design Issues with the try Block | 263 |
| Design Issues with the catch Block | 265 |
| 13 Operator Overloading and User-Defined Conversions | 267 |
| Operator Overloading | 267 |
| Syntax and Example | 268 |
| Overloadable Operators | 271 |
| Restrictions on Operator Overloading | 271 |
| Design Guidelines | 272 |
| User-Defined Conversions | 272 |
| Syntax and Example | 273 |
| 14 Delegates and Event Handlers | 281 |
| Using Delegates as Callback Methods | 281 |
| Defining Delegates as Static Members | 285 |
| Creating Delegates Only When Needed | 287 |
| Delegate Composition | 289 |
| Defining Events with Delegates | 295 |
| PART IV ADVANCED C# | |
| 15 Multithreaded Programming | 303 |
| Threading Basics | 303 |
| Threads and Multitasking | 304 |
| Context Switching | 304 |
| A Multithreaded Application in C# | 305 |
| Working with Threads | 306 |
| AppDomain | 306 |
| The Thread Class | 307 |
| Scheduling Threads | 310 |
| Thread Safety and Synchronization | 314 |
| Protecting Code by Using the Monitor Class | 315 |
| Using Monitor Locks with the C# lock Statement | 319 |
| Synchronizing Code by Using the Mutex Class | 321 |
| Thread Safety and the .NET Classes | 323 |
| Threading Guidelines | 323 |
| When to Use Threads | 323 |
| When Not to Use Threads | 324 |
| 16 Querying Metadata with Reflection | 327 |
| The Reflection API Hierarchy | 327 |
| The Type Class | 328 |
| Retrieving the Type of an Instance | 328 |
| Retrieving the Type from a Name | 329 |
| Interrogating Types | 329 |
| Working with Assemblies and Modules | 332 |
| Iterating Through the Types of an Assembly | 332 |
| Listing an Assembly’s Modules | 335 |
| Late Binding with Reflection | 337 |
| Creating and Executing Code at Run Time | 340 |
| 17 Interoperating with Unmanaged Code | 345 |
| Platform Invocation Services | 346 |
| Declaring the Exported DLL Function | 346 |
| Using Callback Functions with C# | 349 |
| Marshalling and PInvoke | 350 |
| Writing Unsafe Code | 351 |
| Using Pointers in C# | 352 |
| The fixed Statement | 353 |
| COM Interoperability | 355 |
| A Brave New World | 355 |
| Getting Started | 356 |
| Generating Metadata from a COM typelib | 357 |
| Early Binding to COM Components | 360 |
| Using Dynamic Type Discovery to Select COM Interfaces | 362 |
| Late Binding to COM Components | 363 |
| COM Threading Models | 365 |
| 18 Working with Assemblies | 369 |
| Assembly Overview | 369 |
| Manifest Data | 370 |
| Benefits of Assemblies | 371 |
| Assembly Packaging | 371 |
| Assembly Deployment | 371 |
| Assembly Versioning | 372 |
| Building Assemblies | 372 |
| Creating Assemblies that Have Multiple Modules | 373 |
| Creating Shared Assemblies | 375 |
| Working with the Global Assembly Cache | 377 |
| Viewing the Cache | 377 |
| Versioning Assemblies | 379 |
| QFEs and the Default Version Policy | 382 |
| Creating a Safe Mode Configuration File | 382 |
| INDEX | 385 |