Tải bản đầy đủ (.pdf) (953 trang)

The Complete Reference

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (5.77 MB, 953 trang )

C# 4.0:
The Complete Reference
Herbert Schildt
New York Chicago San Francisco
Lisbon London Madrid Mexico City
Milan New Delhi San Juan
Seoul Singapore Sydney Toronto

Copyright © 2010 by The McGraw-Hill Companies. All rights reserved. Except as permitted under the United States Copyright Act of
1976, no part of this publication may be reproduced or distributed in any form or by any means, or stored in a database or retrieval system,
without the prior written permission of the publisher.
ISBN: 978-0-07-174117-0
MHID: 0-07-174117-8
The material in this eBook also appears in the print version of this title: ISBN: 978-0-07-174116-3, MHID: 0-07-174116-X.
All trademarks are trademarks of their respective owners. Rather than put a trademark symbol after every occurrence of a trademarked
name, we use names in an editorial fashion only, and to the benefi t of the trademark owner, with no intention of infringement of the
trademark. Where such designations appear in this book, they have been printed with initial caps.
McGraw-Hill eBooks are available at special quantity discounts to use as premiums and sales promotions, or for use in corporate training
programs. To contact a representative please e-mail us at
All trademarks or copyrights mentioned herein are the possession of their respective owners and McGraw-Hill makes no claim of
ownership by the mention of products that contain these marks.
Information has been obtained by McGraw-Hill from sources believed to be reliable. However, because of the possibility of human or
mechanical error by our sources, McGraw-Hill, or others, McGraw-Hill does not guarantee the accuracy, adequacy, or completeness of any
information and is not responsible for any errors or omissions or the results obtained from the use of such information.
TERMS OF USE
This is a copyrighted work and The McGraw-Hill Companies, Inc. (“McGrawHill”) and its licensors reserve all rights in and to the work.
Use of this work is subject to these terms. Except as permitted under the Copyright Act of 1976 and the right to store and retrieve one
copy of the work, you may not decompile, disassemble, reverse engineer, reproduce, modify, create derivative works based upon, transmit,
distribute, disseminate, sell, publish or sublicense the work or any part of it without McGraw-Hill’s prior consent. You may use the
work for your own noncommercial and personal use; any other use of the work is strictly prohibited. Your right to use the work may be
terminated if you fail to comply with these terms.


THE WORK IS PROVIDED “AS IS.” McGRAW-HILL AND ITS LICENSORS MAKE NO GUARANTEES OR WARRANTIES AS
TO THE ACCURACY, ADEQUACY OR COMPLETENESS OF OR RESULTS TO BE OBTAINED FROM USING THE WORK,
INCLUDING ANY INFORMATION THAT CAN BE ACCESSED THROUGH THE WORK VIA HYPERLINK OR OTHERWISE,
AND EXPRESSLY DISCLAIM ANY WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO IMPLIED
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. McGraw-Hill and its licensors do not
warrant or guarantee that the functions contained in the work will meet your requirements or that its operation will be uninterrupted or
error free. Neither McGraw-Hill nor its licensors shall be liable to you or anyone else for any inaccuracy, error or omission, regardless of
cause, in the work or for any damages resulting therefrom. McGraw-Hill has no responsibility for the content of any information accessed
through the work. Under no circumstances shall McGraw-Hill and/or its licensors be liable for any indirect, incidental, special, punitive,
consequential or similar damages that result from the use of or inability to use the work, even if any of them has been advised of the
possibility of such damages. This limitation of liability shall apply to any claim or cause whatsoever whether such claim or cause arises
in contract, tort or otherwise.

Contents at a Glance
Part I The C# Language
1 The Creation of C# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2 An Overview of C# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3 Data Types, Literals, and Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
4 Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
5 Program Control Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
6 Introducing Classes and Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
7 Arrays and Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
8 A Closer Look at Methods and Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
9 Operator Overloading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
10 Indexers and Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253
11 Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277
12 Interfaces, Structures, and Enumerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319
13 Exception Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345
14 Using I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371
15 Delegates, Events, and Lambda Expressions . . . . . . . . . . . . . . . . . . . . . . . . . 411

16 Namespaces, the Preprocessor, and Assemblies . . . . . . . . . . . . . . . . . . . . . . 449
17 Runtime Type ID, Refl ection, and Attributes . . . . . . . . . . . . . . . . . . . . . . . . 471
18 Generics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 507
19 LINQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 565
20 Unsafe Code, Pointers, Nullable Types, Dynamic Types,
and Miscellaneous Topics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 605
Part II Exploring the C# Library
21 Exploring the System Namespace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 639
22 Strings and Formatting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 691
23 Multithreaded Programming, Part One . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 735
24 Multithreading, Part Two: Exploring the Task Parallel Library
and PLINQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 783
25 Collections, Enumerators, and Iterators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 817
26 Networking Through the Internet Using System.Net . . . . . . . . . . . . . . . . . 895
A Documentation Comment Quick Reference . . . . . . . . . . . . . . . . . . . . . . . . . 921
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 925

Contents
Special Thanks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxi
Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxiii
Part I The C# Language
1 The Creation of C# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
C#’s Family Tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
C: The Beginning of the Modern Age of Programming . . . . . . . . . . . 3
The Creation of OOP and C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
The Internet and Java Emerge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
The Creation of C# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
The Evolution of C# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
How C# Relates to the .NET Framework . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
What Is the .NET Framework? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

How the Common Language Runtime Works . . . . . . . . . . . . . . . . . . . . . . . . . 8
Managed vs. Unmanaged Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
The Common Language Specifi cation . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2 An Overview of C# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Object-Oriented Programming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Encapsulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Polymorphism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
A First Simple Program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Using csc.exe, the C# Command-Line Compiler . . . . . . . . . . . . . . . . . 14
Using the Visual Studio IDE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
The First Sample Program, Line by Line . . . . . . . . . . . . . . . . . . . . . . . . 21
Handling Syntax Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
A Small Variation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
A Second Simple Program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Another Data Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
Two Control Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
The if Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
The for Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
Using Code Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
Semicolons, Positioning, and Indentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
The C# Keywords . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
Identifi ers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
The .NET Framework Class Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35


3 Data Types, Literals, and Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
Why Data Types Are Important . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
C#’s Value Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
Integers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

Floating-Point Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
The decimal Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
Characters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
The bool Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
Some Output Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
Literals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
Hexadecimal Literals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Character Escape Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
String Literals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
A Closer Look at Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
Initializing a Variable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
Dynamic Initialization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
Implicitly Typed Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
The Scope and Lifetime of Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
Type Conversion and Casting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
Automatic Conversions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
Casting Incompatible Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
Type Conversion in Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
Using Casts in Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
4 Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
Arithmetic Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
Increment and Decrement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
Relational and Logical Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
Short-Circuit Logical Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
The Assignment Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
Compound Assignments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
The Bitwise Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
The Bitwise AND, OR, XOR, and NOT Operators . . . . . . . . . . . . . . . 75
The Shift Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
Bitwise Compound Assignments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83

The ? Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
Spacing and Parentheses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
Operator Precedence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
5 Program Control Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
The if Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
Nested ifs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
The if-else-if Ladder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
The switch Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
Nested switch Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94

The for Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
Some Variations on the for Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
The while Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
The do-while Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
The foreach Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
Using break to Exit a Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
Using continue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
return . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
The goto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
6 Introducing Classes and Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
Class Fundamentals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
The General Form of a Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
Defi ne a Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
How Objects Are Created . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
Reference Variables and Assignment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
Add a Method to the Building Class . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
Return from a Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
Return a Value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
Use Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124

Add a Parameterized Method to Building . . . . . . . . . . . . . . . . . . . . . . 127
Avoiding Unreachable Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
Constructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
Parameterized Constructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
Add a Constructor to the Building Class . . . . . . . . . . . . . . . . . . . . . . . 131
The new Operator Revisited . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
Using new with Value Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
Garbage Collection and Destructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
Destructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
The this Keyword . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
7 Arrays and Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
One-Dimensional Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
Multidimensional Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
Two-Dimensional Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
Arrays of Three or More Dimensions . . . . . . . . . . . . . . . . . . . . . . . . . . 144
Initializing Multidimensional Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . 145
Jagged Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
Assigning Array References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
Using the Length Property . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
Using Length with Jagged Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
Implicitly Typed Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
The foreach Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154


Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
Constructing Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
Operating on Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
Arrays of Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
Strings Are Immutable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165

Strings Can Be Used in switch Statements . . . . . . . . . . . . . . . . . . . . . . 166
8 A Closer Look at Methods and Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
Controlling Access to Class Members . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
C#’s Access Modifi ers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
Applying Public and Private Access . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
Controlling Access: A Case Study . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
Pass References to Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
How Arguments Are Passed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
Use ref and out Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
Use ref . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179
Use out . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
Use ref and out on References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
Use a Variable Number of Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
Return Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187
Return an Array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189
Method Overloading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
Overload Constructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196
Invoke an Overloaded Constructor Through this . . . . . . . . . . . . . . . . 199
Object Initializers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
Optional Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202
Optional Arguments vs. Overloading . . . . . . . . . . . . . . . . . . . . . . . . . . 204
Optional Arguments and Ambiguity . . . . . . . . . . . . . . . . . . . . . . . . . . 204
A Practical Example of Optional Arguments . . . . . . . . . . . . . . . . . . . . 205
Named Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206
The Main( ) Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
Return Values from Main( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
Pass Arguments to Main( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
Recursion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210
Understanding static . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213
Static Constructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218

Static Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
9 Operator Overloading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
Operator Overloading Fundamentals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
Overloading Binary Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
Overloading Unary Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224
Handling Operations on C# Built-in Types . . . . . . . . . . . . . . . . . . . . . . . . . . . 228
Overloading the Relational Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232
Overloading true and false . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234

Overloading the Logical Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237
A Simple Approach to Overloading the Logical Operators . . . . . . . . 237
Enabling the Short-Circuit Operators . . . . . . . . . . . . . . . . . . . . . . . . . . 239
Conversion Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243
Operator Overloading Tips and Restrictions . . . . . . . . . . . . . . . . . . . . . . . . . . 247
Another Example of Operator Overloading . . . . . . . . . . . . . . . . . . . . . . . . . . . 248
10 Indexers and Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253
Indexers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253
Creating One-Dimensional Indexers . . . . . . . . . . . . . . . . . . . . . . . . . . . 253
Indexers Can Be Overloaded . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257
Indexers Do Not Require an Underlying Array . . . . . . . . . . . . . . . . . . 259
Multidimensional Indexers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260
Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262
Auto-Implemented Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267
Use Object Initializers with Properties . . . . . . . . . . . . . . . . . . . . . . . . . 268
Property Restrictions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269
Use Access Modifi ers with Accessors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269
Using Indexers and Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272
11 Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277
Inheritance Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277
Member Access and Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280

Using Protected Access . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283
Constructors and Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284
Calling Base Class Constructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286
Inheritance and Name Hiding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290
Using base to Access a Hidden Name . . . . . . . . . . . . . . . . . . . . . . . . . . 291
Creating a Multilevel Hierarchy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293
When Are Constructors Called? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296
Base Class References and Derived Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . 297
Virtual Methods and Overriding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302
Why Overridden Methods? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305
Applying Virtual Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306
Using Abstract Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309
Using sealed to Prevent Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313
The object Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313
Boxing and Unboxing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315
Is object a Universal Data Type? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317
12 Interfaces, Structures, and Enumerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319
Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319
Implementing Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 320
Using Interface References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324
Interface Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326
Interface Indexers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 328


Interfaces Can Be Inherited . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330
Name Hiding with Interface Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331
Explicit Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331
Choosing Between an Interface and an Abstract Class . . . . . . . . . . . . . . . . . . 334
The .NET Standard Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334
Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334

Why Structures? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338
Enumerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340
Initialize an Enumeration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341
Specify the Underlying Type of an Enumeration . . . . . . . . . . . . . . . . 342
Use Enumerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342
13 Exception Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345
The System.Exception Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345
Exception-Handling Fundamentals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346
Using try and catch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346
A Simple Exception Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346
A Second Exception Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 348
The Consequences of an Uncaught Exception . . . . . . . . . . . . . . . . . . . . . . . . . 349
Exceptions Let You Handle Errors Gracefully . . . . . . . . . . . . . . . . . . . . . . . . . 351
Using Multiple catch Clauses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352
Catching All Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353
Nesting try Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354
Throwing an Exception . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355
Rethrowing an Exception . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356
Using fi nally . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357
A Closer Look at the Exception Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359
Commonly Used Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360
Deriving Exception Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362
Catching Derived Class Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 366
Using checked and unchecked . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 368
14 Using I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371
C#’s I/O Is Built Upon Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371
Byte Streams and Character Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . 371
The Predefi ned Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371
The Stream Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372
The Stream Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372

The Byte Stream Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373
The Character Stream Wrapper Classes . . . . . . . . . . . . . . . . . . . . . . . . 374
Binary Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375
Console I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375
Reading Console Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375
Using ReadKey( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377
Writing Console Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379

FileStream and Byte-Oriented File I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380
Opening and Closing a File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380
Reading Bytes from a FileStream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382
Writing to a File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384
Using FileStream to Copy a File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386
Character-Based File I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387
Using StreamWriter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387
Using a StreamReader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 389
Redirecting the Standard Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 390
Reading and Writing Binary Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392
BinaryWriter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392
BinaryReader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392
Demonstrating Binary I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394
Random Access Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 398
Using MemoryStream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 400
Using StringReader and StringWriter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402
The File Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404
Using Copy( ) to Copy a File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404
Using Exists( ) and GetLastAccessTime( ) . . . . . . . . . . . . . . . . . . . . . . 405
Converting Numeric Strings to Their Internal Representation . . . . . . . . . . . 406
15 Delegates, Events, and Lambda Expressions . . . . . . . . . . . . . . . . . . . . . . . . . 411
Delegates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 411

Delegate Method Group Conversion . . . . . . . . . . . . . . . . . . . . . . . . . . 414
Using Instance Methods as Delegates . . . . . . . . . . . . . . . . . . . . . . . . . . 414
Multicasting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 416
Covariance and Contravariance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 418
System.Delegate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420
Why Delegates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420
Anonymous Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420
Anonymous Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 421
Pass Arguments to an Anonymous Method . . . . . . . . . . . . . . . . . . . . . 422
Return a Value from an Anonymous Method . . . . . . . . . . . . . . . . . . . 422
Use Outer Variables with Anonymous Methods . . . . . . . . . . . . . . . . . 424
Lambda Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425
The Lambda Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425
Expression Lambdas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 426
Statement Lambdas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 428
Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 431
A Multicast Event Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 433
Instance Methods vs. Static Methods as Event Handlers . . . . . . . . . . 434
Using Event Accessors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436
Miscellaneous Event Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 441
Use Anonymous Methods and Lambda Expressions with Events . . . . . . . . 441


.NET Event Guidelines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 442
Use EventHandler<TEventArgs> and EventHandler . . . . . . . . . . . . 444
Applying Events: A Case Study . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 445
16 Namespaces, the Preprocessor, and Assemblies . . . . . . . . . . . . . . . . . . . . . . 449
Namespaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 449
Declaring a Namespace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 450
Namespaces Prevent Name Confl icts . . . . . . . . . . . . . . . . . . . . . . . . . . 452

using . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 453
A Second Form of using . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 455
Namespaces Are Additive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 456
Namespaces Can Be Nested . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 458
The Global Namespace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 459
Using the :: Namespace Alias Qualifi er . . . . . . . . . . . . . . . . . . . . . . . . 459
The Preprocessor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 463
#defi ne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 464
#if and #endif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 464
#else and #elif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 466
#undef . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 467
#error . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 468
#warning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 468
#line . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 468
#region and #endregion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 468
#pragma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 469
Assemblies and the internal Access Modifi er . . . . . . . . . . . . . . . . . . . . . . . . . 469
The internal Access Modifi er . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 470
17 Runtime Type ID, Refl ection, and Attributes . . . . . . . . . . . . . . . . . . . . . . . . 471
Runtime Type Identifi cation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 471
Testing a Type with is . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 471
Using as . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 472
Using typeof . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 474
Refl ection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 475
The Refl ection Core: System.Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 475
Using Refl ection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 477
Obtaining Information About Methods . . . . . . . . . . . . . . . . . . . . . . . . 477
Calling Methods Using Refl ection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 481
Obtaining a Type’s Constructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 483
Obtaining Types from Assemblies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 487

Fully Automating Type Discovery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 493
Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 495
Attribute Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 495
Positional vs. Named Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 499
Three Built-in Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 503
AttributeUsage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 503
The Conditional Attribute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 503
The Obsolete Attribute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 505

18 Generics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 507
What Are Generics? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 507
A Simple Generics Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 508
Generic Types Differ Based on Their Type Arguments . . . . . . . . . . . . 511
How Generics Improve Type Safety . . . . . . . . . . . . . . . . . . . . . . . . . . . 511
A Generic Class with Two Type Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . 514
The General Form of a Generic Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 515
Constrained Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 515
Using a Base Class Constraint . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 516
Using an Interface Constraint . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 524
Using the new( ) Constructor Constraint . . . . . . . . . . . . . . . . . . . . . . . 528
The Reference Type and Value Type Constraints . . . . . . . . . . . . . . . . 529
Using a Constraint to Establish a Relationship Between
Two Type Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 532
Using Multiple Constraints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 533
Creating a Default Value of a Type Parameter . . . . . . . . . . . . . . . . . . . . . . . . . 534
Generic Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 535
Creating a Generic Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 536
Using Explicit Type Arguments to Call a Generic Method . . . . . . . . 539
Using a Constraint with a Generic Method . . . . . . . . . . . . . . . . . . . . . 539
Generic Delegates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 539

Generic Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 541
Comparing Instances of a Type Parameter . . . . . . . . . . . . . . . . . . . . . . . . . . . . 544
Generic Class Hierarchies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 548
Using a Generic Base Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 549
A Generic Derived Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 551
Overriding Virtual Methods in a Generic Class . . . . . . . . . . . . . . . . . . . . . . . . 552
Overloading Methods That Use Type Parameters . . . . . . . . . . . . . . . . . . . . . 553
Covariance and Contravariance in Generic Type Parameters . . . . . . . . . . . . 555
Using Covariance in a Generic Interface . . . . . . . . . . . . . . . . . . . . . . . . 555
Using Contravariance in a Generic Interface . . . . . . . . . . . . . . . . . . . . 558
Variant Delegates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 561
How Generic Types Are Instantiated . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 563
Some Generic Restrictions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 564
Final Thoughts on Generics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 564
19 LINQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 565
LINQ Fundamentals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 566
A Simple Query . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 566
A Query Can Be Executed More Than Once . . . . . . . . . . . . . . . . . . . . 568
How the Data Types in a Query Relate . . . . . . . . . . . . . . . . . . . . . . . . . 569
The General Form of a Query . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 570
Filter Values with where . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 571
Sort Results with orderby . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 572
A Closer Look at select . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 576
Use Nested from Clauses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 580


Group Results with group . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 581
Use into to Create a Continuation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 583
Use let to Create a Variable in a Query . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 585
Join Two Sequences with join . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 586

Anonymous Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 589
Create a Group Join . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 591
The Query Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 594
The Basic Query Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 594
Create Queries by Using the Query Methods . . . . . . . . . . . . . . . . . . . 595
Query Syntax vs. Query Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 597
More Query-Related Extension Methods . . . . . . . . . . . . . . . . . . . . . . . 597
Deferred vs. Immediate Query Execution . . . . . . . . . . . . . . . . . . . . . . . . . . . . 600
Expression Trees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 601
Extension Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 602
PLINQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 604
20 Unsafe Code, Pointers, Nullable Types, Dynamic Types,
and Miscellaneous Topics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 605
Unsafe Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 605
Pointer Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 606
Using unsafe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 607
Using fi xed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 608
Accessing Structure Members Through a Pointer . . . . . . . . . . . . . . . . 609
Pointer Arithmetic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 609
Pointer Comparisons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 611
Pointers and Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 611
Pointers and Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 613
Multiple Indirection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 614
Arrays of Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 615
stackalloc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 616
Creating Fixed-Size Buffers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 616
Nullable Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 618
Nullable Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 618
Nullable Objects in Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 620
The ?? Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 621

Nullable Objects and the Relational and Logical Operators . . . . . . . 622
Partial Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 623
Partial Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 624
Create a Dynamic Type with dynamic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 625
COM Interoperability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 629
Friend Assemblies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 630
Miscellaneous Keywords . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 630
lock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 630
readonly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 631

const and volatile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 632
The using Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 632
extern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 633
Part II Exploring the C# Library
21 Exploring the System Namespace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 639
The Members of System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 639
The Math Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 641
The .NET Structures Corresponding to the Built-in Value Types . . . . . . . . . 646
The Integer Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 647
The Floating-Point Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 649
Decimal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 652
Char . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 657
The Boolean Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 662
The Array Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 663
Sorting and Searching Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 672
Reversing an Array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 675
Copying an Array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 676
Using a Predicate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 677
Using an Action . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 678
BitConverter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 680

Generating Random Numbers with Random . . . . . . . . . . . . . . . . . . . . . . . . . 681
Memory Management and the GC Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 682
Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 684
Tuple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 685
The IComparable and IComparable<T> Interfaces . . . . . . . . . . . . . . . . . . . . . 685
The IEquatable<T> Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 686
The IConvertible Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 686
The ICloneable Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 686
IFormatProvider and IFormattable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 688
IObservable<T> and IObserver<T> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 689
22 Strings and Formatting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 691
Strings in C# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 691
The String Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 692
The String Constructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 692
The String Field, Indexer, and Property . . . . . . . . . . . . . . . . . . . . . . . . 693
The String Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 693
The String Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 693
Padding and Trimming Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 711
Inserting, Removing, and Replacing . . . . . . . . . . . . . . . . . . . . . . . . . . . 713
Changing Case . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 714
Using the Substring( ) Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 714
The String Extension Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 715


Formatting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 715
Formatting Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 715
The Numeric Format Specifi ers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 716
Understanding Argument Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . 718
Using String.Format( ) and ToString( ) to Format Data . . . . . . . . . . . . . . . . . 719
Using String.Format( ) to Format Values . . . . . . . . . . . . . . . . . . . . . . . 719

Using ToString( ) to Format Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 721
Creating a Custom Numeric Format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 722
The Custom Format Placeholder Characters . . . . . . . . . . . . . . . . . . . . 722
Formatting Date and Time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 726
Creating a Custom Date and Time Format . . . . . . . . . . . . . . . . . . . . . . 728
Formatting Time Spans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 730
Formatting Enumerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 732
23 Multithreaded Programming, Part One . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 735
Multithreading Fundamentals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 736
The Thread Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 737
Creating and Starting a Thread . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 737
Some Simple Improvements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 739
Creating Multiple Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 740
Determining When a Thread Ends . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 742
Passing an Argument to a Thread . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 745
The IsBackground Property . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 747
Thread Priorities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 747
Synchronization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 750
An Alternative Approach . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 754
The Monitor Class and lock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 755
Thread Communication Using Wait( ), Pulse( ), and PulseAll( ) . . . . . . . . . 756
An Example That Uses Wait( ) and Pulse( ) . . . . . . . . . . . . . . . . . . . . . 756
Deadlock and Race Conditions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 760
Using MethodImplAttribute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 760
Using a Mutex and a Semaphore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 762
The Mutex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 762
The Semaphore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 766
Using Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 769
The Interlocked Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 772
Synchronization Classes Added by .NET 4.0 . . . . . . . . . . . . . . . . . . . . . . . . . . 773

Terminating a Thread Via Abort( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 774
An Abort( ) Alternative . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 775
Canceling Abort( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 777
Suspending and Resuming a Thread . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 778
Determining a Thread’s State . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 779
Using the Main Thread . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 779
Additional Multithreading Features Added by .NET 4.0 . . . . . . . . . . . . . . . . 780
Multithreading Tips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 781
Starting a Separate Task . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 781

24 Multithreading, Part Two: Exploring the Task Parallel Library
and PLINQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 783
Two Approaches to Parallel Programming . . . . . . . . . . . . . . . . . . . . . . . . . . . . 784
The Task Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 784
Creating a Task . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 784
Use a Task ID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 787
Using Wait Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 789
Calling Dispose( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 791
Using TaskFactory to Start a Task . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 792
Use a Lambda Expression as a Task . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 792
Create a Task Continuation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 794
Returning a Value from a Task . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 796
Cancelling a Task and Using AggregateException . . . . . . . . . . . . . . . . . . . . . 798
Some Other Task Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 801
The Parallel Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 801
Parallelizing Tasks via Invoke( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 802
Using the For( ) Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 804
Using the ForEach( ) Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 810
Exploring PLINQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 812
ParallelEnumerable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 812

Parallelizing a Query with AsParallel( ) . . . . . . . . . . . . . . . . . . . . . . . . 812
Using AsOrdered( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 814
Cancelling a Parallel Query . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 814
Other PLINQ Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 816
PLINQ Effi ciency Concerns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 816
25 Collections, Enumerators, and Iterators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 817
Collections Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 817
The Non-Generic Collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 818
The Non-Generic Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 819
The DictionaryEntry Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 823
The Non-Generic Collection Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . 824
Storing Bits with BitArray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 840
The Specialized Collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 843
The Generic Collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 843
The Generic Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 844
The KeyValuePair<TKey, TValue> Structure . . . . . . . . . . . . . . . . . . . . 848
The Generic Collection Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 848
The Concurrent Collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 869
Storing User-Defi ned Classes in Collections . . . . . . . . . . . . . . . . . . . . . . . . . . 873
Implementing IComparable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 875
Implementing IComparable for Non-Generic Collections . . . . . . . . . 875
Implementing IComparable<T> for Generic Collections . . . . . . . . . . 877
Using an IComparer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 878
Using a Non-Generic IComparer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 879
Using a Generic IComparer<T> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 880


Using StringComparer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 881
Accessing a Collection via an Enumerator . . . . . . . . . . . . . . . . . . . . . . . . . . . . 882
Using an Enumerator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 883

Using IDictionaryEnumerator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 884
Implementing IEnumerable and IEnumerator . . . . . . . . . . . . . . . . . . . . . . . . 885
Using Iterators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 887
Stopping an Iterator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 889
Using Multiple yield Directives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 890
Creating a Named Iterator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 890
Creating a Generic Iterator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 892
Collection Initializers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 893
26 Networking Through the Internet Using System.Net . . . . . . . . . . . . . . . . . 895
The System.Net Members . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 895
Uniform Resource Identifi ers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 897
Internet Access Fundamentals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 898
WebRequest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 899
WebResponse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 900
HttpWebRequest and HttpWebResponse . . . . . . . . . . . . . . . . . . . . . . . 901
A Simple First Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 901
Handling Network Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 904
Exceptions Generated by Create( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 904
Exceptions Generated by GetReponse( ) . . . . . . . . . . . . . . . . . . . . . . . . 905
Exceptions Generated by GetResponseStream( ) . . . . . . . . . . . . . . . . . 905
Using Exception Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 905
The URI Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 907
Accessing Additional HTTP Response Information . . . . . . . . . . . . . . . . . . . . 908
Accessing the Header . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 908
Accessing Cookies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 910
Using the LastModifi ed Property . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 912
MiniCrawler: A Case Study . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 913
Using WebClient . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 916
A Documentation Comment Quick Reference . . . . . . . . . . . . . . . . . . . . . . . . . 921
The XML Comment Tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 921

Compiling Documentation Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 922
An XML Documentation Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 923
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 925

I
The C# Language
P
art 1 discusses the elements of the C# language, including its
keywords, syntax, and operators. Also described are several
foundational C# techniques, such as using I/O and reflection,
which are tightly linked with the C# language.
CHAPTER 1 The Creation of C#
CHAPTER 2 An Overview of C#
CHAPTER 3 Data Types, Literals,
and Variables
CHAPTER 4 Operators
CHAPTER 5 Program Control
Statements
CHAPTER 6 Introducing Classes
and Objects
CHAPTER 7 Arrays and Strings
CHAPTER 8 A Closer Look at
Methods and Classes
CHAPTER 9 Operator
Overloading
CHAPTER 10 Indexers and
Properties
CHAPTER 11 Inheritance
CHAPTER 12 Interfaces,
Structures, and Enumerations

CHAPTER 13 Exception Handling
CHAPTER 14 Using I/O
CHAPTER 15 Delegates, Events,
and Lambda Expressions
CHAPTER 16 Namespaces, the
Preprocessor, and Assemblies
CHAPTER 17 Runtime Type ID,
Refl ection, and Attributes
CHAPTER 18 Generics
CHAPTER 19 LINQ
CHAPTER 20 Unsafe Code,
Pointers, Nullable Types,
Dynamic Types, and
Miscellaneous Topics
PART

1
The Creation of C#
C
# is Microsoft’s premier language for .NET development. It leverages time-tested
features with cutting-edge innovations and provides a highly usable, efficient way
to write programs for the modern enterprise computing environment. It is, by any
measure, one of the most important languages of the twenty-first century.
The purpose of this chapter is to place C# into its historical context, including the forces
that drove its creation, its design philosophy, and how it was influenced by other computer
languages. This chapter also explains how C# relates to the .NET Framework. As you will
see, C# and the .NET Framework work together to create a highly refined programming
environment.
C#’s Family Tree
Computer languages do not exist in a void. Rather, they relate to one another, with each

new language influenced in one form or another by the ones that came before. In a process
akin to cross-pollination, features from one language are adapted by another, a new
innovation is integrated into an existing context, or an older construct is removed. In
this way, languages evolve and the art of programming advances. C# is no exception.
C# inherits a rich programming legacy. It is directly descended from two of the world’s
most successful computer languages: C and C++. It is closely related to another: Java.
Understanding the nature of these relationships is crucial to understanding C#. Thus, we
begin our examination of C# by placing it in the historical context of these three languages.
C: The Beginning of the Modern Age of Programming
The creation of C marks the beginning of the modern age of programming. C was invented
by Dennis Ritchie in the 1970s on a DEC PDP-11 that used the UNIX operating system.
While some earlier languages, most notably Pascal, had achieved significant success, it
was C that established the paradigm that still charts the course of programming today.
C grew out of the structured programming revolution of the 1960s. Prior to structured
programming, large programs were difficult to write because the program logic tended
to degenerate into what is known as “spaghetti code,” a tangled mass of jumps, calls, and
returns that is difficult to follow. Structured languages addressed this problem by adding
well-defined control statements, subroutines with local variables, and other improvements.
Through the use of structured techniques programs became better organized, more reliable,
and easier to manage.
3
CHAPTER

4
Part I: The C# Language
Although there were other structured languages at the time, C was the first to successfully
combine power, elegance, and expressiveness. Its terse, yet easy-to-use syntax coupled with
its philosophy that the programmer (not the language) was in charge quickly won many
converts. It can be a bit hard to understand from today’s perspective, but C was a breath of
fresh air that programmers had long awaited. As a result, C became the most widely used

structured programming language of the 1980s.
However, even the venerable C language had its limits. One of the most troublesome
was its inability to handle large programs. The C language hits a barrier once a project
reaches a certain size, and after that point, C programs are difficult to understand and
maintain. Precisely where this limit is reached depends upon the program, the programmer,
and the tools at hand, but there is always a threshold beyond which a C program becomes
unmanageable.
The Creation of OOP and C++
By the late 1970s, the size of many projects was near or at the limits of what structured
programming methodologies and the C language could handle. To solve this problem, a
new way to program began to emerge. This method is called object-oriented programming
(OOP). Using OOP, a programmer could handle much larger programs. The trouble was
that C, the most popular language at the time, did not support object-oriented programming.
The desire for an object-oriented version of C ultimately led to the creation of C++.
C++ was invented by Bjarne Stroustrup beginning in 1979 at Bell Laboratories in Murray
Hill, New Jersey. He initially called the new language “C with Classes.” However, in 1983 the
name was changed to C++. C++ contains the entire C language. Thus, C is the foundation
upon which C++ is built. Most of the additions that Stroustrup made to C were designed to
support object-oriented programming. In essence, C++ is the object-oriented version of C.
By building upon the foundation of C, Stroustrup provided a smooth migration path to OOP.
Instead of having to learn an entirely new language, a C programmer needed to learn only
a few new features before reaping the benefits of the object-oriented methodology.
C++ simmered in the background during much of the 1980s, undergoing extensive
development. By the beginning of the 1990s, C++ was ready for mainstream use, and its
popularity exploded. By the end of the decade, it had become the most widely used
programming language. Today, C++ is still the preeminent language for the development of
high-performance system code.
It is critical to understand that the invention of C++ was not an attempt to create an
entirely new programming language. Instead, it was an enhancement to an already highly
successful language. This approach to language development—beginning with an existing

language and moving it forward—established a trend that continues today.
The Internet and Java Emerge
The next major advance in programming languages is Java. Work on Java, which was
originally called Oak, began in 1991 at Sun Microsystems. The main driving force behind
Java’s design was James Gosling. Patrick Naughton, Chris Warth, Ed Frank, and Mike
Sheridan also played a role.
Java is a structured, object-oriented language with a syntax and philosophy derived
from C++. The innovative aspects of Java were driven not so much by advances in the art
of programming (although some certainly were), but rather by changes in the computing

PART I
Chapter 1: The Creation of C#
5
PART IPART I
environment. Prior to the mainstreaming of the Internet, most programs were written,
compiled, and targeted for a specific CPU and a specific operating system. While it has
always been true that programmers like to reuse their code, the ability to port a program
easily from one environment to another took a backseat to more pressing problems.
However, with the rise of the Internet, in which many different types of CPUs and
operating systems are connected, the old problem of portability reemerged with a
vengeance. To solve the problem of portability, a new language was needed, and this
new language was Java.
Although the single most important aspect of Java (and the reason for its rapid
acceptance) is its ability to create cross-platform, portable code, it is interesting to note
that the original impetus for Java was not the Internet, but rather the need for a platform-
independent language that could be used to create software for embedded controllers. In
1993, it became clear that the issues of cross-platform portability found when creating code
for embedded controllers are also encountered when attempting to create code for the
Internet. Remember: the Internet is a vast, distributed computing universe in which many
different types of computers live. The same techniques that solved the portability problem

on a small scale could be applied to the Internet on a large scale.
Java achieved portability by translating a program’s source code into an intermediate
language called bytecode. This bytecode was then executed by the Java Virtual Machine
(JVM). Therefore, a Java program could run in any environment for which a JVM was
available. Also, since the JVM is relatively easy to implement, it was readily available for
a large number of environments.
Java’s use of bytecode differed radically from both C and C++, which were nearly
always compiled to executable machine code. Machine code is tied to a specific CPU and
operating system. Thus, if you wanted to run a C/C++ program on a different system, it
needed to be recompiled to machine code specifically for that environment. Therefore, to
create a C/C++ program that would run in a variety of environments, several different
executable versions of the program would be needed. Not only was this impractical, it was
expensive. Java’s use of an intermediate language was an elegant, cost-effective solution.
It is also a solution that C# would adapt for its own purposes.
As mentioned, Java is descended from C and C++. Its syntax is based on C, and its object
model is evolved from C++. Although Java code is neither upwardly nor downwardly
compatible with C or C++, its syntax is sufficiently similar that the large pool of existing
C/C++ programmers could move to Java with very little effort. Furthermore, because Java
built upon and improved an existing paradigm, Gosling, et al., were free to focus their
attentions on the new and innovative features. Just as Stroustrup did not need to “reinvent
the wheel” when creating C++, Gosling did not need to create an entirely new language
when developing Java. Moreover, with the creation of Java, C and C++ became an accepted
substrata upon which to base a new computer language.
The Creation of C#
While Java successfully addresses many of the issues surrounding portability in the Internet
environment, there are still features that it lacks. One is cross-language interoperability, also
called mixed-language programming. This is the ability for the code produced by one language
to work easily with the code produced by another. Cross-language interoperability is needed
for the creation of large, distributed software systems. It is also desirable for programming


6
Part I: The C# Language
software components because the most valuable component is one that can be used by the
widest variety of computer languages, in the greatest number of operating environments.
Another feature lacking in Java is full integration with the Windows platform. Although
Java programs can be executed in a Windows environment (assuming that the Java Virtual
Machine has been installed), Java and Windows are not closely coupled. Since Windows is
the mostly widely used operating system in the world, lack of direct support for Windows
is a drawback to Java.
To answer these and other needs, Microsoft developed C#. C# was created at Microsoft
late in the 1990s and was part of Microsoft’s overall .NET strategy. It was first released in its
alpha version in the middle of 2000. C#’s chief architect was Anders Hejlsberg. Hejlsberg is
one of the world’s leading language experts, with several notable accomplishments to his
credit. For example, in the 1980s he was the original author of the highly successful and
influential Turbo Pascal, whose streamlined implementation set the standard for all future
compilers.
C# is directly related to C, C++, and Java. This is not by accident. These are three of
the most widely used—and most widely liked—programming languages in the world.
Furthermore, at the time of C#’s creation, nearly all professional programmers knew C,
C++, and/or Java. By building C# upon a solid, well-understood foundation, C# offered an
easy migration path from these languages. Since it was neither necessary nor desirable for
Hejlsberg to “reinvent the wheel,” he was free to focus on specific improvements and
innovations.
The family tree for C# is shown in Figure 1-1. The grandfather of C# is C. From C, C#
derives its syntax, many of its keywords, and its operators. C# builds upon and improves
the object model defined by C++. If you know C or C++, then you will feel at home with C#.
C# and Java have a bit more complicated relationship. As explained, Java is also
descended from C and C++. It too shares the C/C++ syntax and object model. Like Java,
C# is designed to produce portable code. However, C# is not descended from Java.
Instead, C# and Java are more like cousins, sharing a common ancestry, but differing in

many important ways. The good news, though, is that if you know Java, then many C#
concepts will be familiar. Conversely, if in the future you need to learn Java, then many
of the things you learn about C# will carry over.
FIGURE 1-1
The C# family tree

PART I
Chapter 1: The Creation of C#
7
PART IPART I
C# contains many innovative features that we will examine at length throughout the
course of this book, but some of its most important relate to its built-in support for software
components. In fact, C# has been characterized as being a component-oriented language
because it contains integral support for the writing of software components. For example,
C# includes features that directly support the constituents of components, such as properties,
methods, and events. However, C#’s ability to work in a secure, mixed-language environment
is perhaps its most important component-oriented feature.
The Evolution of C#
Since its original 1.0 release, C# has been evolving at a rapid pace. Not long after C# 1.0,
Microsoft released version 1.1. It contained many minor tweaks but added no major
features. However, the situation was much different with the release of C# 2.0.
C# 2.0 was a watershed event in the lifecycle of C# because it added many new features,
such as generics, partial types, and anonymous methods, that fundamentally expanded the
scope, power, and range of the language. Version 2.0 firmly put C# at the forefront of
computer language development. It also demonstrated Microsoft’s long-term commitment
to the language.
The next major release of C# was 3.0. Because of the many new features added by C#
2.0, one might have expected the development of C# to slow a bit, just to let programmers
catch up, but this was not the case. With the release of C# 3.0, Microsoft once again put C#
on the cutting edge of language design, this time adding a set of innovative features that

redefined the programming landscape. These include lambda expressions, language-
integrated query (LINQ), extension methods, and implicitly typed variables, among others.
Although all of the new 3.0 features were important, the two that had the most high-profile
impact on the language were LINQ and lambda expressions. They added a completely new
dimension to C# and further emphasized its lead in the ongoing evolution of computer
languages.
The current release is C# 4.0, and that is the version of C# described by this book. C# 4.0
builds on the strong foundation established by the previous three major releases, adding
several new features. Perhaps the most important are named and optional arguments. Named
arguments let you link an argument with a parameter by name. Optional arguments give you
a way to specify a default argument for a parameter. Another important new feature is the
dynamic type, which is used to declare objects that are type-checked at runtime, rather than
compile time. Covariance and contravariance support is also provided for type parameters,
which are supported by new uses of the in and out keywords. For those programmers using
the Office Automation APIs (and COM in general), access has been simplified. (Office
Automation and COM are outside the scope of this book). In general, the new 4.0 features
further streamline coding and improve the usability of C#.
There is another major feature that relates directly to C# 4.0 programming, but which
is provided by the .NET Framework 4.0. This is support for parallel programming through
two major new features. The first is the Task Parallel Library (TPL) and the second is
Parallel LINQ (PLINQ). Both of these dramatically enhance and simplify the process of
creating programs that use concurrency. Both also make it easier to create multithreaded
code that automatically scales to utilize the number of processors available in the computer.
Put directly, multicore computers are becoming commonplace, and the ability to parallelize
your code to take advantage of them is an increasingly important part of nearly every C#
programmer’s job description. Because of the significant impact the TPL and PLINQ are
having on programming, both are covered in this book.

8
Part I: The C# Language

How C# Relates to the .NET Framework
Although C# is a computer language that can be studied on its own, it has a special
relationship to its runtime environment, the .NET Framework. The reason for this is twofold.
First, C# was initially designed by Microsoft to create code for the .NET Framework. Second,
the libraries used by C# are the ones defined by the .NET Framework. Thus, even though it
is theoretically possible to separate C# the language from the .NET environment, the two are
closely linked. Because of this, it is important to have a general understanding of the .NET
Framework and why it is important to C#.
What Is the .NET Framework?
The .NET Framework defines an environment that supports the development and execution
of highly distributed, component-based applications. It enables differing computer languages
to work together and provides for security, program portability, and a common programming
model for the Windows platform. As it relates to C#, the .NET Framework defines two very
important entities. The first is the Common Language Runtime (CLR). This is the system that
manages the execution of your program. Along with other benefits, the Common Language
Runtime is the part of the .NET Framework that enables programs to be portable, supports
mixed-language programming, and provides for secure execution.
The second entity is the .NET class library. This library gives your program access to the
runtime environment. For example, if you want to perform I/O, such as displaying something
on the screen, you will use the .NET class library to do it. If you are new to programming,
then the term class may be new. Although it is explained in detail later in this book, for now
a brief definition will suffice: a class is an object-oriented construct that helps organize
programs. As long as your program restricts itself to the features defined by the .NET class
library, your programs can run anywhere that the .NET runtime system is supported. Since
C# automatically uses the .NET Framework class library, C# programs are automatically
portable to all .NET environments.
How the Common Language Runtime Works
The Common Language Runtime manages the execution of .NET code. Here is how it
works: When you compile a C# program, the output of the compiler is not executable code.
Instead, it is a file that contains a special type of pseudocode called Microsoft Intermediate

Language (MSIL). MSIL defines a set of portable instructions that are independent of any
specific CPU. In essence, MSIL defines a portable assembly language. One other point:
although MSIL is similar in concept to Java’s bytecode, the two are not the same.
It is the job of the CLR to translate the intermediate code into executable code when a
program is run. Thus, any program compiled to MSIL can be run in any environment for
which the CLR is implemented. This is part of how the .NET Framework achieves portability.
Microsoft Intermediate Language is turned into executable code using a JIT compiler.
“JIT” stands for “Just-In-Time.” The process works like this: When a .NET program is
executed, the CLR activates the JIT compiler. The JIT compiler converts MSIL into native
code on demand as each part of your program is needed. Thus, your C# program actually
executes as native code even though it is initially compiled into MSIL. This means that your
program runs nearly as fast as it would if it had been compiled to native code in the first

PART I
Chapter 1: The Creation of C#
9
PART IPART I
place, but it gains the portability benefits of MSIL. Also, during compilation, code
verification takes place to ensure type safety (unless a security policy has been established
that avoids this step).
In addition to MSIL, one other thing is output when you compile a C# program:
metadata. Metadata describes the data used by your program and enables your code to
interact easily with other code. The metadata is contained in the same file as the MSIL.
Managed vs. Unmanaged Code
In general, when you write a C# program, you are creating what is called managed code.
Managed code is executed under the control of the Common Language Runtime, as just
described. Because it is running under the control of the CLR, managed code is subject to
certain constraints—and derives several benefits. The constraints are easily described and
met: the compiler must produce an MSIL file targeted for the CLR (which C# does) and use
the .NET class library (which C# does). The benefits of managed code are many, including

modern memory management, the ability to mix languages, better security, support for
version control, and a clean way for software components to interact.
The opposite of managed code is unmanaged code. Unmanaged code does not execute
under the Common Language Runtime. Thus, Windows programs prior to the creation of
the .NET Framework use unmanaged code. It is possible for managed code and unmanaged
code to work together, so the fact that C# generates managed code does not restrict its ability
to operate in conjunction with preexisting programs.
The Common Language Specification
Although all managed code gains the benefits provided by the CLR, if your code will be
used by other programs written in different languages, then, for maximum usability, it
should adhere to the Common Language Specification (CLS). The CLS describes a set of
features that different .NET-compatible languages have in common. CLS compliance is
especially important when creating software components that will be used by other
languages. The CLS includes a subset of the Common Type System (CTS). The CTS defines
the rules concerning data types. Of course, C# supports both the CLS and the CTS.

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×