Pro C# 2005
and the
.NET 2.0 Platform
■ ■ ■
Andrew Troelsen
4193FM.qxd 8/14/05 2:41 PM Page i
Pro C# 2005 and the .NET 2.0 Platform
Copyright © 2005 by Andrew Troelsen
All rights reserved. No part of this work may be reproduced or transmitted in any form or by any means,
electronic or mechanical, including photocopying, recording, or by any information storage or retrieval
system, without the prior written permission of the copyright owner and the publisher.
ISBN: 1-59059-419-3
Printed and bound in the United States of America 9 8 7 6 5 4 3 2 1
Trademarked names may appear in this book. Rather than use a trademark symbol with every occurrence
of a trademarked name, we use the names only in an editorial fashion and to the benefit of the trademark
owner, with no intention of infringement of the trademark.
Lead Editor: Ewan Buckingham
Technical Reviewer: Gavin Smyth
Editorial Board: Steve Anglin, Dan Appleman, Ewan Buckingham, Gary Cornell, Tony Davis, Jason Gilmore,
Jonathan Hassell, Chris Mills, Dominic Shakeshaft, Jim Sumser
Associate Publisher and Project Manager: Grace Wong
Copy Edit Manager: Nicole LeClerc
Copy Editors: Nicole LeClerc, Ami Knox
Assistant Production Director: Kari Brooks-Copony
Production Editor: Laura Cheu
Compositor and Artist: Kinetic Publishing Services, LLC
Proofreader: Nancy Sixsmith
Indexers: Kevin Broccoli and Dan Mabbutt
Interior Designer: Van Winkle Design Group
Cover Designer: Kurt Krames
CHAPTER 2 Building C# Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
PART 2
■ ■ ■
The C# Programming Language
CHAPTER 3 C# Language Fundamentals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
CHAPTER 4 Object-Oriented Programming with C# . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
CHAPTER 5 Understanding Object Lifetime. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179
CHAPTER 6 Understanding Structured Exception Handling . . . . . . . . . . . . . . . . . . . . . 197
CHAPTER 7 Interfaces and Collections. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
CHAPTER 8 Callback Interfaces, Delegates, and Events. . . . . . . . . . . . . . . . . . . . . . . . 255
CHAPTER 9 Advanced C# Type Construction Techniques . . . . . . . . . . . . . . . . . . . . . . . 289
CHAPTER 10 Understanding Generics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321
PART 3
■ ■ ■
Programming with .NET Assemblies
CHAPTER 11 Introducing .NET Assemblies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
CHAPTER 12 Type Reflection, Late Binding, and Attribute-Based Programming . . . . 391
CHAPTER 13 Processes, AppDomains, Contexts, and CLR Hosts . . . . . . . . . . . . . . . . . 425
CHAPTER 14 Building Multithreaded Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 449
CHAPTER 15 Understanding CIL and the Role of Dynamic Assemblies . . . . . . . . . . . . 477
v
4193FM.qxd 8/14/05 2:41 PM Page v
PART 4
■ ■ ■
Programming with the .NET Libraries
CHAPTER 16 The System.IO Namespace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 517
CHAPTER 17 Understanding Object Serialization. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 545
CHAPTER 18 The .NET Remoting Layer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 565
CHAPTER 19 Building a Better Window with System.Windows.Forms . . . . . . . . . . . . 605
CHAPTER 20 Rendering Graphical Data with GDI+ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 649
(the CLR, CTS, and CLS)
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
The Role of the Base Class Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
What C# Brings to the Table. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Additional .NET-Aware Programming Languages . . . . . . . . . . . . . . . . . . . . . . . . . 8
Life in a Multilanguage World . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
An Overview of .NET Assemblies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Single-File and Multifile Assemblies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
The Role of the Common Intermediate Language . . . . . . . . . . . . . . . . . . . . . . . . 11
Benefits of CIL. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Compiling CIL to Platform-Specific Instructions. . . . . . . . . . . . . . . . . . . . . 14
The Role of .NET Type Metadata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
The Role of the Assembly Manifest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Understanding the Common Type System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
CTS Class Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
CTS Structure Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
CTS Interface Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
CTS Enumeration Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
CTS Delegate Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
vii
4193FM.qxd 8/14/05 2:41 PM Page vii
CTS Type Members. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Intrinsic CTS Data Types. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Understanding the Common Language Specification . . . . . . . . . . . . . . . . . . . . 19
Ensuring CLS Compliance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
Understanding the Common Language Runtime . . . . . . . . . . . . . . . . . . . . . . . . 20
The Assembly/Namespace/Type Distinction . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
Accessing a Namespace Programmatically. . . . . . . . . . . . . . . . . . . . . . . . 24
Referencing External Assemblies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
Using ildasm.exe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
Building .NET Applications Using Visual C# 2005 Express . . . . . . . . . . . . . . . . . 50
■CONTENTSviii
4193FM.qxd 8/14/05 2:41 PM Page viii
The Big Kahuna: Building .NET Applications Using Visual Studio 2005. . . . . . . . 51
Learning the Lay of the Land: Visual Studio 2005 . . . . . . . . . . . . . . . . . . . 52
The Solution Explorer Utility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
The Class View Utility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
The Code Definition Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
The Object Browser Utility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
Integrated Support for Code Refactoring . . . . . . . . . . . . . . . . . . . . . . . . . . 55
Code Expansions and Surround with Technology . . . . . . . . . . . . . . . . . . . 57
The Visual Class Designer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
Object Test Bench. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
The Integrated Help System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
A Partial Catalogue of Additional .NET Development Tools . . . . . . . . . . . . . . . . . 61
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
PART 2
■ ■ ■
The C# Programming Language
■CHAPTER 3 C# Language Fundamentals. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
The Anatomy of a Simple C# Program. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
Variations on the Main() Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
Processing Command-Line Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
Specifying Command-Line Arguments with Visual Studio 2005 . . . . . . . . 68
An Interesting Aside: The System.Environment Class . . . . . . . . . . . . . . . . . . . . . 68
Defining Classes and Creating Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
The Role of Constructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
Is That a Memory Leak? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
Defining an “Application Object” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
The System.Console Class. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
The if/else Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
The switch Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
Understanding Value Types and Reference Types . . . . . . . . . . . . . . . . . . . . . . . . 96
Value Types, References Types, and the Assignment Operator . . . . . . . . . 97
Value Types Containing Reference Types . . . . . . . . . . . . . . . . . . . . . . . . . 99
Passing Reference Types by Value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
Passing Reference Types by Reference . . . . . . . . . . . . . . . . . . . . . . . . . . 102
Value and Reference Types: Final Details. . . . . . . . . . . . . . . . . . . . . . . . . 103
Understanding Boxing and Unboxing Operations . . . . . . . . . . . . . . . . . . . . . . . 104
Some Practical (Un)Boxing Examples. . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
Unboxing Custom Value Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
Working with .NET Enumerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
The System.Enum Base Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
The Master Class: System.Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
The Default Behavior of System.Object . . . . . . . . . . . . . . . . . . . . . . . . . . 112
Overriding Some Default Behaviors of System.Object . . . . . . . . . . . . . . . . . . . 113
Overriding System.Object.ToString() . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
Overriding System.Object.Equals(). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
Overriding System.Object.GetHashCode() . . . . . . . . . . . . . . . . . . . . . . . . 115
Testing the Overridden Members . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
Static Members of System.Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
The System Data Types (and C# Shorthand Notation). . . . . . . . . . . . . . . . . . . . 117
Experimenting with Numerical Data Types. . . . . . . . . . . . . . . . . . . . . . . . 120
Members of System.Boolean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
Members of System.Char . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
Parsing Values from String Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
System.DateTime and System.TimeSpan . . . . . . . . . . . . . . . . . . . . . . . . 122
The System.String Data Type. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
Basic String Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
Escape Characters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
Another Form of Encapsulation: Class Properties . . . . . . . . . . . . . . . . . . 149
Internal Representation of C# Properties . . . . . . . . . . . . . . . . . . . . . . . . . 151
Controlling Visibility Levels of Property get/set Statements. . . . . . . . . . . 153
Read-Only and Write-Only Properties. . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
Static Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
The Second Pillar: C#’s Inheritance Support . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
Controlling Base Class Creation with base. . . . . . . . . . . . . . . . . . . . . . . . 156
Regarding Multiple Base Classes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
Keeping Family Secrets: The protected Keyword. . . . . . . . . . . . . . . . . . . 157
Preventing Inheritance: Sealed Classes . . . . . . . . . . . . . . . . . . . . . . . . . . 158
Programming for Containment/Delegation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
Nested Type Definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
The Third Pillar: C#’s Polymorphic Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
The virtual and override Keywords. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
Revisiting the sealed Keyword . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
■CONTENTS
xi
4193FM.qxd 8/14/05 2:41 PM Page xi
Understanding Abstract Classes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
Enforcing Polymorphic Activity: Abstract Methods. . . . . . . . . . . . . . . . . . 165
Member Hiding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
C# Casting Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
Determining the “Type of” Employee . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
Numerical Casts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
Understanding C# Partial Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
Documenting C# Source Code via XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
XML Code Comment Format Characters . . . . . . . . . . . . . . . . . . . . . . . . . 176
Transforming XML Code Comments. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
■CHAPTER 5 Understanding Object Lifetime . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179
System-Level Exceptions (System.SystemException) . . . . . . . . . . . . . . . . . . . . 208
Application-Level Exceptions (System.ApplicationException) . . . . . . . . . . . . . . 208
Building Custom Exceptions, Take One . . . . . . . . . . . . . . . . . . . . . . . . . . 209
Building Custom Exceptions, Take Two . . . . . . . . . . . . . . . . . . . . . . . . . . 210
Building Custom Exceptions, Take Three . . . . . . . . . . . . . . . . . . . . . . . . . 210
Processing Multiple Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212
Generic catch Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213
Rethrowing Exceptions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214
Inner Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214
The Finally Block . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215
Who Is Throwing What? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216
The Result of Unhandled Exception . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217
Debugging Unhandled Exceptions Using Visual Studio 2005 . . . . . . . . . . . . . . 218
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219
■CHAPTER 7 Interfaces and Collections. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
Defining Interfaces in C# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
Implementing an Interface in C# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
Contrasting Interfaces to Abstract Base Classes . . . . . . . . . . . . . . . . . . . . . . . . 224
Invoking Interface Members at the Object Level . . . . . . . . . . . . . . . . . . . . . . . . 224
Obtaining Interface References: The as Keyword . . . . . . . . . . . . . . . . . . 225
Obtaining Interface References: The is Keyword . . . . . . . . . . . . . . . . . . . 225
Interfaces As Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
Interfaces As Return Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228
Arrays of Interface Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228
Understanding Explicit Interface Implementation . . . . . . . . . . . . . . . . . . . . . . . 229
Resolving Name Clashes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231
Building Interface Hierarchies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232
Interfaces with Multiple Base Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . 233
Implementing Interfaces Using Visual Studio 2005 . . . . . . . . . . . . . . . . . . . . . . 234
Building Enumerable Types (IEnumerable and IEnumerator). . . . . . . . . . . . . . . 235
Delegates As Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271
Analyzing the Delegation Code. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274
Understanding Delegate Covariance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275
Understanding C# Events. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277
Events Under the Hood . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278
Listening to Incoming Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279
Simplifying Event Registration Using Visual Studio 2005 . . . . . . . . . . . . 280
A “Prim-and-Proper” Event . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281
Understanding C# Anonymous Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282
Accessing “Outer” Variables. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284
C# Method Group Conversions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286
■CHAPTER 9 Advanced C# Type Construction Techniques. . . . . . . . . . . . . . . 289
Building a Custom Indexer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289
A Variation of the Garage Indexer. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291
Internal Representation of Type Indexers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292
Indexers: Final Details . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293
Understanding Operator Overloading. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293
Overloading Binary Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294
And What of the += and –+ Operators? . . . . . . . . . . . . . . . . . . . . . . . . . 295
Overloading Unary Operators. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296
Overloading Equality Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296
Overloading Comparison Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297
■CONTENTSxiv
4193FM.qxd 8/14/05 2:41 PM Page xiv
The Internal Representation of Overloaded Operators. . . . . . . . . . . . . . . . . . . . 298
Interacting with Overloaded Operators from
Overloaded Operator–Challenged Languages . . . . . . . . . . . . . . . . . . . . . . . 299
Final Thoughts Regarding Operator Overloading . . . . . . . . . . . . . . . . . . . . . . . . 301
Understanding Custom Type Conversions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301
Creating Generic Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340
Creating Generic Delegates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341
Simulating Generic Delegates Under .NET 1.1. . . . . . . . . . . . . . . . . . . . . 342
A Brief Word Regarding Nested Delegates. . . . . . . . . . . . . . . . . . . . . . . . 343
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343
■CONTENTS
xv
4193FM.qxd 8/14/05 2:41 PM Page xv
PART 3
■ ■ ■
Programming with .NET Assemblies
■CHAPTER 11 Introducing .NET Assemblies. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
The Role of .NET Assemblies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
Assemblies Promote Code Reuse. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
Assemblies Establish a Type Boundary . . . . . . . . . . . . . . . . . . . . . . . . . . 348
Assemblies Are Versionable Units. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 348
Assemblies Are Self-Describing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 348
Assemblies Are Configurable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 348
Understanding the Format of a .NET Assembly . . . . . . . . . . . . . . . . . . . . . . . . . 349
The Win32 File Header . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349
The CLR File Header. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350
CIL Code, Type Metadata, and the Assembly Manifest . . . . . . . . . . . . . . 351
Optional Assembly Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352
Single-File and Multifile Assemblies. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352
Building and Consuming a Single-File Assembly. . . . . . . . . . . . . . . . . . . . . . . . 354
Exploring the Manifest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357
Exploring the CIL. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 358
Exploring the Type Metadata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 358
Building a C# Client Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359
Building a Visual Basic .NET Client Application . . . . . . . . . . . . . . . . . . . . 360
Understanding the <codeBase> Element . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385
The System.Configuration Namespace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387
The Machine Configuration File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388
The Assembly Binding “Big Picture” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 389
■CHAPTER 12 Type Reflection, Late Binding, and Attribute-Based
Programming
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391
The Necessity of Type Metadata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391
Viewing (Partial) Metadata for the EngineState Enumeration . . . . . . . . . 392
Viewing (Partial) Metadata for the Car Type . . . . . . . . . . . . . . . . . . . . . . . 393
Examining a TypeRef . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394
Documenting the Defining Assembly . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394
Documenting Referenced Assemblies . . . . . . . . . . . . . . . . . . . . . . . . . . . 394
Documenting String Literals. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395
Understanding Reflection. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395
The System.Type Class. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396
Obtaining a Type Reference Using System.Object.GetType(). . . . . . . . . . 397
Obtaining a Type Reference Using System.Type.GetType() . . . . . . . . . . . 397
Obtaining a Type Reference Using typeof() . . . . . . . . . . . . . . . . . . . . . . . 398
Building a Custom Metadata Viewer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 398
Reflecting on Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 398
Reflecting on Fields and Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 398
Reflecting on Implemented Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . 399
Displaying Various Odds and Ends. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399
Implementing Main(). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399
Reflecting on Method Parameters and Return Values . . . . . . . . . . . . . . . 401
Dynamically Loading Assemblies. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402
Reflecting on Shared Assemblies. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404
Understanding Late Binding. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 406
An Overview of Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 426
Interacting with Processes Under the .NET Platform. . . . . . . . . . . . . . . . . . . . . 427
Enumerating Running Processes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 429
Investigating a Specific Process. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430
Investigating a Process’s Thread Set . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430
Investigating a Process’s Module Set. . . . . . . . . . . . . . . . . . . . . . . . . . . . 432
Starting and Stopping Processes Programmatically . . . . . . . . . . . . . . . . 434
Understanding .NET Application Domains . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 435
Enumerating a Process’s AppDomains. . . . . . . . . . . . . . . . . . . . . . . . . . . 436
Programmatically Creating New AppDomains . . . . . . . . . . . . . . . . . . . . . 437
Programmatically Unloading AppDomains . . . . . . . . . . . . . . . . . . . . . . . . 439
Understanding Object Context Boundaries . . . . . . . . . . . . . . . . . . . . . . . . . . . . 440
Context-Agile and Context-Bound Types . . . . . . . . . . . . . . . . . . . . . . . . . 441
Defining a Context-Bound Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 442
Inspecting an Object’s Context. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 442
Summarizing Processes, AppDomains, and Context . . . . . . . . . . . . . . . . . . . . . 444
■CONTENTSxviii
4193FM.qxd 8/14/05 2:41 PM Page xviii
Hosting the Common Language Runtime . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 444
Side-by-Side Execution of the CLR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 445
Loading a Specific Version of the CLR . . . . . . . . . . . . . . . . . . . . . . . . . . . 446
Additional CLR Hosts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 447
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 447
■CHAPTER 14 Building Multithreaded Applications . . . . . . . . . . . . . . . . . . . . . . . 449
The Process/AppDomain/Context/Thread Relationship. . . . . . . . . . . . . . . . . . . 449
The Problem of Concurrency and the Role of
Thread Synchronization. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 450
A Brief Review of the .NET Delegate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 451
The Asynchronous Nature of Delegates. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 453
The BeginInvoke() and EndInvoke() Methods . . . . . . . . . . . . . . . . . . . . . . 453
■CONTENTS
xix
4193FM.qxd 8/14/05 2:41 PM Page xix
The Role of CIL Opcodes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 479
The CIL Opcode/CIL Mnemonic Distinction . . . . . . . . . . . . . . . . . . . . . . . 479
Pushing and Popping: The Stack-Based Nature of CIL . . . . . . . . . . . . . . . . . . . 480
Understanding Round-trip Engineering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 481
The Role of CIL Code Labels. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 483
Interacting with CIL: Modifying an *.il File . . . . . . . . . . . . . . . . . . . . . . . . 484
Compiling CIL Code Using ilasm.exe . . . . . . . . . . . . . . . . . . . . . . . . . . . . 485
Compiling CIL Code Using SharpDevelop. . . . . . . . . . . . . . . . . . . . . . . . . 486
Compiling CIL Code Using ILIDE#. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 486
The Role of peverify.exe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 487
Understanding CIL Directives and Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . 487
Specifying Externally Referenced Assemblies in CIL . . . . . . . . . . . . . . . . 488
Defining the Current Assembly in CIL. . . . . . . . . . . . . . . . . . . . . . . . . . . . 488
Defining Namespaces in CIL. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 489
Defining Class Types in CIL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 489
Defining and Implementing Interfaces in CIL . . . . . . . . . . . . . . . . . . . . . . 490
Defining Structures in CIL. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 491
Defining Enums in CIL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 491
Compiling the CILTypes.il file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 491
.NET Base Class Library, C#, and CIL Data Type Mappings. . . . . . . . . . . . . . . . 492
Defining Type Members in CIL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 493
Defining Field Data in CIL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 493
Defining Type Constructors in CIL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 494
Defining Properties in CIL. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 494
Defining Member Parameters. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 495
Examining CIL Opcodes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 495
Considering the .maxstack Directive . . . . . . . . . . . . . . . . . . . . . . . . . . . . 497
Enumerating Files with the DirectoryInfo Type. . . . . . . . . . . . . . . . . . . . . 521
Creating Subdirectories with the DirectoryInfo Type . . . . . . . . . . . . . . . . 522
Working with the Directory Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 523
Working with the DriveInfo Class Type. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 524
Working with the FileInfo Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 525
The FileInfo.Create() Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 526
The FileInfo.Open() Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 527
The FileInfo.OpenRead() and FileInfo.OpenWrite() Methods. . . . . . . . . . . 528
The FileInfo.OpenText() Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 528
The FileInfo.CreateText() and FileInfo.AppendText() Methods . . . . . . . . . 528
Working with the File Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 529
New .NET 2.0 File Members . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 530
The Abstract Stream Class. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 531
Working with FileStreams. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 532
Working with StreamWriters and StreamReaders. . . . . . . . . . . . . . . . . . . . . . . 533
Writing to a Text File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 534
Reading from a Text File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 535
Directly Creating StreamWriter/StreamReader Types . . . . . . . . . . . . . . . 536
Working with StringWriters and StringReaders . . . . . . . . . . . . . . . . . . . . . . . . . 536
Working with BinaryWriters and BinaryReaders . . . . . . . . . . . . . . . . . . . . . . . . 538
Programmatically “Watching” Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 540
Performing Asynchronous File I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 542
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 543
■CHAPTER 17 Understanding Object Serialization . . . . . . . . . . . . . . . . . . . . . . . . 545
Understanding Object Serialization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 545
The Role of Object Graphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 546
Configuring Objects for Serialization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 547
Public Fields, Private Fields, and Public Properties . . . . . . . . . . . . . . . . . 548
■CONTENTS
xxi
Basic Deployment of a .NET Remoting Project . . . . . . . . . . . . . . . . . . . . . . . . . 574
Building Your First Distributed Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 575
Building the General Assembly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 575
Building the Server Assembly. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 576
Building the SimpleRemoteObjectClient.exe Assembly . . . . . . . . . . . . . 577
Testing the Remoting Application. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 578
Understanding the ChannelServices Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 578
Understanding the RemotingConfiguration Type . . . . . . . . . . . . . . . . . . . . . . . . 580
Revisiting the Activation Mode of WKO Types . . . . . . . . . . . . . . . . . . . . . . . . . . 581
Deploying the Server to a Remote Machine . . . . . . . . . . . . . . . . . . . . . . . . . . . 582
Leveraging the TCP Channel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 582
A Brief Word Regarding the IpcChannel. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 583
■CONTENTSxxii
4193FM.qxd 8/14/05 2:41 PM Page xxii
Remoting Configuration Files. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 584
Building Server-Side *.config Files. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 584
Building Client-Side *.config Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 585
Working with MBV Objects. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 586
Building the General Assembly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 586
Building the Server Assembly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 587
Building the Client Assembly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 588
Understanding Client-Activated Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 590
The Lease-Based Lifetime of CAO/WKO-Singleton Objects . . . . . . . . . . . . . . . 592
The Default Leasing Behavior . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 592
Altering the Default Lease Characteristics . . . . . . . . . . . . . . . . . . . . . . . 594
Server-Side Lease Adjustment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 595
Client-Side Lease Adjustment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 596
Server-Side (and Client-Side) Lease Sponsorship. . . . . . . . . . . . . . . . . . . . . . . 596
Alternative Hosts for Remote Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 597
Hosting Remote Objects Using a Windows Service . . . . . . . . . . . . . . . . 597
4193FM.qxd 8/14/05 2:41 PM Page xxiii
Working with MenuStrips and ContextMenuStrips . . . . . . . . . . . . . . . . . . . . . . 626
Adding a TextBox to the MenuStrip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 629
Creating a Context Menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 630
Checking Menu Items. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 632
Working with StatusStrips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 633
Designing the Menu System. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 634
Designing the StatusStrip. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 634
Working with the Timer Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 637
Toggling the Display . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 638
Displaying the Menu Selection Prompts . . . . . . . . . . . . . . . . . . . . . . . . . 639
Establishing a “Ready” State . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 639
Working with ToolStrips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 639
Working with ToolStripContainers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 643
Building an MDI Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 646
Building the Parent Form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 646
Building the Child Form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 647
Spawning Child Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 647
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 648
■CHAPTER 20 Rendering Graphical Data with GDI+. . . . . . . . . . . . . . . . . . . . . . . 649
A Survey of the GDI+ Namespaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 649
An Overview of the System.Drawing Namespace . . . . . . . . . . . . . . . . . . . . . . . 650
The System.Drawing Utility Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 651
The Point(F) Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 651
The Rectangle(F) Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 652
The Region Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 653
Understanding the Graphics Class. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 653
Understanding Paint Sessions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 655
Invalidating the Form’s Client Area. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 656
Obtaining a Graphics Object Outside of a Paint Event Handler . . . . . . . . 657