|
|
xvii | |
|
|
xix | |
Foreword |
|
xxi | |
Foreword to the Second Edition |
|
xxiii | |
Foreword to the First Edition |
|
xxv | |
Preface |
|
xxvii | |
Acknowledgments |
|
xxxiii | |
About the Authors |
|
xxxv | |
About the Annotators |
|
xxxvii | |
|
|
1 | (8) |
|
1.1 Qualities of a Well-Designed Framework |
|
|
3 | (6) |
|
1.1.1 Well-Designed Frameworks Are Simple |
|
|
3 | (1) |
|
1.1.2 Well-Designed Frameworks Are Expensive to Design |
|
|
4 | (2) |
|
1.1.3 Well-Designed Frameworks Are Full of Trade-Offs |
|
|
6 | (1) |
|
1.1.4 Well-Designed Frameworks Borrow from the Past |
|
|
6 | (1) |
|
1.1.5 Well-Designed Frameworks Are Designed to Evolve |
|
|
7 | (1) |
|
1.1.6 Well-Designed Frameworks Are Integrated |
|
|
7 | (1) |
|
1.1.7 Well-Designed Frameworks Are Consistent |
|
|
7 | (2) |
|
2 Framework Design Fundamentals |
|
|
9 | (32) |
|
2.1 Progressive Frameworks |
|
|
12 | (3) |
|
2.2 Fundamental Principles of Framework Design |
|
|
15 | (21) |
|
2.2.1 The Principle of Scenario-Driven Design |
|
|
16 | (7) |
|
2.2.2 The Principle of Low Barrier to Entry |
|
|
23 | (6) |
|
2.2.3 The Principle of Self-Documenting Object Models |
|
|
29 | (7) |
|
2.2 A The Principle of Layered Architecture |
|
|
36 | (5) |
|
|
41 | (42) |
|
3.1 Capitalization Conventions |
|
|
42 | (10) |
|
3.1.1 Capitalization Rules for Identifiers |
|
|
42 | (3) |
|
3.1.2 Capitalizing Acronyms |
|
|
45 | (3) |
|
3.1.3 Capitalizing Compound Words and Common Terms |
|
|
48 | (3) |
|
|
51 | (1) |
|
3.2 General Naming Conventions |
|
|
52 | (6) |
|
|
52 | (3) |
|
3.2.2 Using Abbreviations and Acronyms |
|
|
55 | (1) |
|
3.2.3 Avoiding Language-Specific Names |
|
|
56 | (2) |
|
3.2 A Naming New Versions of Existing APIs |
|
|
58 | (3) |
|
3.3 Names of Assemblies, DLLs, and Packages |
|
|
61 | (2) |
|
|
63 | (4) |
|
3.4.1 Namespaces and Type Name Conflicts |
|
|
65 | (2) |
|
3.5 Names of Classes, Structs, and Interfaces |
|
|
67 | (7) |
|
3.5.1 Names of Generic Type Parameters |
|
|
70 | (1) |
|
3.5.2 Names of Common Types |
|
|
71 | (1) |
|
3.5.3 Naming Enumerations |
|
|
72 | (2) |
|
3.6 Names of Type Members |
|
|
74 | (4) |
|
|
74 | (1) |
|
3.6.2 Names of Properties |
|
|
75 | (2) |
|
|
77 | (1) |
|
|
78 | (1) |
|
|
79 | (2) |
|
3.7.1 Naming Operator Overload Parameters |
|
|
80 | (1) |
|
|
81 | (2) |
|
|
83 | (52) |
|
|
85 | (4) |
|
4.2 Choosing Between Class and Struct |
|
|
89 | (3) |
|
4.3 Choosing Between Class and Interface |
|
|
92 | (8) |
|
4.4 Abstract Class Design |
|
|
100 | (2) |
|
|
102 | (2) |
|
|
104 | (2) |
|
|
106 | (5) |
|
|
111 | (13) |
|
4.8.1 Designing Flag Enums |
|
|
119 | (4) |
|
4.8.2 Adding Values to Enums |
|
|
123 | (1) |
|
|
124 | (3) |
|
4.10 Types and Assembly Metadata |
|
|
127 | (2) |
|
4.11 Strongly Typed Strings |
|
|
129 | (6) |
|
|
135 | (92) |
|
5.1 General Member Design Guidelines |
|
|
135 | (23) |
|
|
136 | (12) |
|
5.1.2 Implementing Interface Members Explicitly |
|
|
148 | (4) |
|
5.1.3 Choosing Between Properties and Methods |
|
|
152 | (6) |
|
|
158 | (7) |
|
5.2.1 Indexed Property Design |
|
|
161 | (2) |
|
5.2.2 Property Change Notification Events |
|
|
163 | (2) |
|
|
165 | (10) |
|
5.3.1 Type Constructor Guidelines |
|
|
172 | (3) |
|
|
175 | (5) |
|
|
180 | (4) |
|
|
184 | (8) |
|
|
192 | (8) |
|
5.7.1 Overloading Operator == |
|
|
198 | (1) |
|
5.7.2 Conversion Operators |
|
|
198 | (2) |
|
5.73 Inequality Operators |
|
|
200 | (2) |
|
|
202 | (18) |
|
5.8.1 Choosing Between Enum and Boolean Parameters |
|
|
205 | (2) |
|
5.8.2 Validating Arguments |
|
|
207 | (3) |
|
|
210 | (4) |
|
5.8.4 Members with Variable Number of Parameters |
|
|
214 | (4) |
|
|
218 | (2) |
|
5.9 Using Tuples in Member Signatures |
|
|
220 | (7) |
|
6 Designing for Extensibility |
|
|
227 | (22) |
|
6.1 Extensibility Mechanisms |
|
|
227 | (15) |
|
|
228 | (2) |
|
|
230 | (1) |
|
6.1.3 Events and Callbacks |
|
|
231 | (6) |
|
|
237 | (2) |
|
6.1.5 Abstractions (Abstract Types and Interfaces) |
|
|
239 | (3) |
|
|
242 | (2) |
|
|
244 | (5) |
|
|
249 | (24) |
|
|
254 | (6) |
|
7.2 Choosing the Right Type of Exception to Throw |
|
|
260 | (13) |
|
7.2.1 Error Message Design |
|
|
264 | (1) |
|
|
265 | (6) |
|
7.2.3 Wrapping Exceptions |
|
|
271 | (2) |
|
73 Using Standard Exception Types |
|
|
273 | (6) |
|
7.3.1 Exception and SystemException |
|
|
274 | (1) |
|
7.3.2 ApplicationException |
|
|
274 | (1) |
|
7.3.3 InvalidOperationException |
|
|
274 | (1) |
|
7.3.4 Argument Exception, ArgumentNull Exception, and ArgumentOutOfRangeException |
|
|
275 | (1) |
|
73.5 Null Reference Exception, Index Out Of Range Exception, and Access Violation Exception |
|
|
276 | (1) |
|
7.3.6 Stack Overflow Exception |
|
|
276 | (1) |
|
73.7 Out OF Memory Exception |
|
|
277 | (2) |
|
7.3.8 ComException, SEHException, and Execution Engine Exception |
|
|
278 | (1) |
|
7.3.9 Operation Canceled Exception and Task Canceled Exception |
|
|
278 | (1) |
|
|
278 | (1) |
|
7.3.11 Platform Not Supported Exception |
|
|
279 | (1) |
|
7 A Designing Custom Exceptions |
|
|
279 | (8) |
|
7.5 Exceptions and Performance |
|
|
281 | (6) |
|
7.5.1 The Tester--Doer Pattern |
|
|
281 | (1) |
|
|
282 | (5) |
|
|
287 | (42) |
|
|
287 | (4) |
|
|
291 | (3) |
|
|
294 | (12) |
|
8.3.1 Collection Parameters |
|
|
296 | (2) |
|
8.3.2 Collection Properties and Return Values |
|
|
298 | (4) |
|
8.3.3 Choosing Between Arrays and Collections |
|
|
302 | (1) |
|
8.3.4 Implementing Custom Collections |
|
|
303 | (3) |
|
8.4 DateTime and DateTimeOffset |
|
|
306 | (2) |
|
|
308 | (1) |
|
8.6 IComparable<T> and IEquatable<T> |
|
|
309 | (2) |
|
|
311 | (1) |
|
|
311 | (1) |
|
|
312 | (7) |
|
|
312 | (3) |
|
|
315 | (1) |
|
|
316 | (3) |
|
|
319 | (2) |
|
|
321 | (2) |
|
8.11.1 System. Uri Implementation Guidelines |
|
|
322 | (1) |
|
|
323 | (1) |
|
|
324 | (5) |
|
8.13.1 Equality Operators on Value Types |
|
|
327 | (1) |
|
8.13.2 Equality Operators on Reference Types |
|
|
328 | (1) |
|
|
329 | (136) |
|
|
329 | (10) |
|
9.1.1 Component-Oriented Design |
|
|
331 | (3) |
|
|
334 | (1) |
|
9.1.3 Aggregate Component Guidelines |
|
|
335 | (4) |
|
|
339 | (26) |
|
9.2.1 Choosing Between the Async Patterns |
|
|
339 | (2) |
|
9.2.2 Task-Based Async Pattern |
|
|
341 | (7) |
|
9.2.3 Async Method Return Types |
|
|
348 | (3) |
|
9.2.4 Making an Async Variant of an Existing Synchronous Method |
|
|
351 | (4) |
|
9.2.5 Implementation Guidelines for Async Pattern Consistency |
|
|
355 | (6) |
|
9.2.7 Classic Async Pattern |
|
|
361 | (1) |
|
9.2.8 Event-Based Async Pattern |
|
|
361 | (1) |
|
|
362 | (1) |
|
9.2.10 IAsyncEnumerable<T> |
|
|
362 | (3) |
|
9.3 Dependency Properties |
|
|
365 | (7) |
|
9.3.1 Dependency Property Design |
|
|
366 | (3) |
|
9.3.2 Attached Dependency Property Design |
|
|
369 | (1) |
|
9.3.3 Dependency Property Validation |
|
|
370 | (1) |
|
9.3.4 Dependency Property Change Notifications |
|
|
371 | (1) |
|
9.3.5 Dependency Property Value Coercion |
|
|
371 | (1) |
|
|
372 | (22) |
|
9.4.1 Basic Dispose Pattern |
|
|
375 | (8) |
|
|
383 | (4) |
|
|
387 | (4) |
|
|
391 | (3) |
|
|
394 | (6) |
|
|
400 | (1) |
|
|
400 | (2) |
|
9.6.2 Ways of Implementing LINQ Support |
|
|
402 | (1) |
|
9.6.3 Supporting LINQ through IEnumerable<T> |
|
|
402 | (1) |
|
9.6.4 Supporting LINQ through IQueryable<T> |
|
|
403 | (1) |
|
9.6.5 Supporting LINQ through the Query Pattern |
|
|
404 | (4) |
|
9.7 Optional Feature Pattern |
|
|
408 | (4) |
|
9.8 Covariance and Contravariance |
|
|
412 | (11) |
|
|
415 | (2) |
|
|
417 | (3) |
|
9.8.3 Simulated Covariance Pattern |
|
|
420 | (3) |
|
|
423 | (3) |
|
|
426 | (1) |
|
|
427 | (3) |
|
9.12 Operating on Buffers |
|
|
430 | (34) |
|
9.12.1 Data Transformation Operations |
|
|
445 | (6) |
|
9.12.2 Writing Fixed or Predetermined Sizes to a Buffer |
|
|
451 | (1) |
|
9.12.3 Writing Values to Buffers with the Try-Write Pattern |
|
|
452 | (6) |
|
9.12.4 Partial Writes to Buffers and OperationStatus |
|
|
458 | (6) |
|
|
464 | (1) |
|
A C# Coding Style Conventions |
|
|
465 | (22) |
|
A.1 General Style Conventions |
|
|
466 | (14) |
|
|
466 | (3) |
|
|
469 | (1) |
|
|
470 | (2) |
|
A.1.4 Vertical Whitespace |
|
|
472 | (1) |
|
|
473 | (2) |
|
|
475 | (5) |
|
|
480 | (2) |
|
|
482 | (1) |
|
|
483 | (4) |
|
|
487 | (36) |
|
B.3 Obsolete Guidance from Naming Guidelines |
|
|
488 | (1) |
|
|
488 | (1) |
|
B.4 Obsolete Guidance from Type Design Guidelines |
|
|
489 | (2) |
|
B.4.1 Types and Namespaces |
|
|
489 | (2) |
|
B.5 Obsolete Guidance from Member Design |
|
|
491 | (1) |
|
|
491 | (1) |
|
B.7 Obsolete Guidance from Exceptions |
|
|
492 | (1) |
|
B.7.4 Designing Custom Exceptions |
|
|
492 | (1) |
|
B.8 Obsolete Guidance from Usage Guidelines |
|
|
493 | (9) |
|
|
493 | (9) |
|
B.9 Obsolete Guidance from Common Design Patterns |
|
|
502 | (15) |
|
|
502 | (15) |
|
|
517 | (6) |
|
C Sample API Specification |
|
|
523 | (6) |
|
|
529 | (28) |
|
|
530 | (1) |
|
D.1.1 Changing the Name of an Assembly |
|
|
530 | (1) |
|
|
531 | (1) |
|
D.2.1 Adding a Namespace That Conflicts with an Existing Type |
|
|
531 | (1) |
|
|
532 | (1) |
|
D.3.1 Changing the Name or Casing of a Namespace |
|
|
532 | (1) |
|
|
532 | (1) |
|
D.4.1 Moving a Type via [ TypeForwardedTo] |
|
|
532 | (1) |
|
D.4.2 Moving a Type Without [ TypeForwardedTo] |
|
|
533 | (1) |
|
|
533 | (1) |
|
|
533 | (1) |
|
|
534 | (5) |
|
D.6.1 Sealing an Unsealed Type |
|
|
534 | (1) |
|
D.6.2 Unsealing a Sealed Type |
|
|
534 | (1) |
|
D.6.3 Changing the Case of a Type Name |
|
|
534 | (1) |
|
D.6.4 Changing a Type Name |
|
|
535 | (1) |
|
D.6.5 Changing the Namespace for a Type |
|
|
535 | (1) |
|
D.6.6 Adding readonly on a struct |
|
|
535 | (1) |
|
D.6.7 Removing readonly from a struct |
|
|
535 | (1) |
|
D.6.8 Adding a Base Interface to an Existing Interface |
|
|
536 | (1) |
|
D.6.9 Adding the Second Declaration of a Generic Interface |
|
|
536 | (1) |
|
D.6.10 Changing a class to a struct |
|
|
537 | (1) |
|
D.6.11 Changing a struct to a class |
|
|
537 | (1) |
|
D.6.12 Changing a struct to a re f struct |
|
|
538 | (1) |
|
D.6.13 Changing a ref struct to a (Non-ref) struct |
|
|
538 | (1) |
|
|
539 | (2) |
|
D.7.1 Masking Base Members with new |
|
|
539 | (1) |
|
D.7.2 Adding abstract Members |
|
|
539 | (1) |
|
D.7.3 Adding Members to an Unsealed Type |
|
|
539 | (1) |
|
D.7.4 Adding an over ride Member to an Unsealed Type |
|
|
540 | (1) |
|
D.7.5 Adding the First Reference Type Field to a struct |
|
|
540 | (1) |
|
D.7.6 Adding a Member to an Interface |
|
|
541 | (1) |
|
|
541 | (1) |
|
D.8.1 Moving Members to a Base Class |
|
|
541 | (1) |
|
D.8.2 Moving Members to a Base Interface |
|
|
541 | (1) |
|
D.8.3 Moving Members to a Derived Type |
|
|
542 | (1) |
|
|
542 | (2) |
|
D.9.1 Removing a Finalizer from an Unsealed Type |
|
|
542 | (1) |
|
D.9.2 Removing a Finalizer from a Sealed Type |
|
|
542 | (1) |
|
D.9.3 Removing a Non-override Member |
|
|
543 | (1) |
|
D.9.4 Removing an override of a virtual Member |
|
|
543 | (1) |
|
D.9.5 Removing an override of an abstract Member |
|
|
543 | (1) |
|
D.9.6 Removing or Renaming Private Fields on Serializable Types |
|
|
544 | (1) |
|
|
544 | (1) |
|
D.10.1 Adding the First Overload of a Member |
|
|
545 | (1) |
|
D.10.2 Adding Alternative-Parameter Overloads for a Reference Type Parameter |
|
|
545 | (1) |
|
D.11 Changing Member Signatures |
|
|
545 | (8) |
|
D.11.1 Renaming a Method Parameter |
|
|
545 | (1) |
|
D.11.2 Adding or Removing a Method Parameter |
|
|
546 | (1) |
|
D.11.3 Changing a Method Parameter Type |
|
|
546 | (1) |
|
D.11.4 Reordering Method Parameters of Differing Types |
|
|
547 | (1) |
|
D.11.5 Reordering Method Parameters of The Same Type |
|
|
547 | (1) |
|
D.11.6 Changing a Method Return Type |
|
|
547 | (1) |
|
D.11.7 Changing the Type of a Property |
|
|
548 | (1) |
|
D.11.8 Changing Member Visibility from pub lie to Any Other Visibility |
|
|
548 | (1) |
|
D.11.9 Changing Member Visibility from protected to public |
|
|
548 | (1) |
|
D.11.10 Changing a virtual (or abstract) Member from protected to public |
|
|
549 | (1) |
|
D.11.11 Adding or Removing the static Modifier |
|
|
549 | (1) |
|
D.11.12 Changing to or from Passing a Parameter by Reference |
|
|
549 | (1) |
|
D.11.13 Changing By-Reference Parameter Styles |
|
|
550 | (1) |
|
D.11.14 Adding the readonly Modifier to a struct Method |
|
|
550 | (1) |
|
D.11.15 Removing the readonly Modifier from a struct Method |
|
|
551 | (1) |
|
D.11.16 Changing a Parameter from Required to Optional |
|
|
551 | (1) |
|
D.11.17 Changing a Parameter from Optional to Required |
|
|
551 | (1) |
|
D.11.18 Changing the Default Value for an Optional Parameter |
|
|
552 | (1) |
|
D.11.19 Changing the Value of a cons t Field |
|
|
552 | (1) |
|
D.11.20 Changing an abstract Member to virtual |
|
|
553 | (1) |
|
D.11.21 Changing a virtual Member to abstract |
|
|
553 | (1) |
|
D.11.22 Changing a Non-virtual Member to virtual |
|
|
553 | (1) |
|
|
553 | (3) |
|
D.12.1 Changing Runtime Error Exceptions to Usage Error Exceptions |
|
|
553 | (1) |
|
D.12.2 Changing Usage Error Exceptions to Functioning Behavior |
|
|
554 | (1) |
|
D.12.3 Changing the Type of Values Returned from a Method |
|
|
554 | (1) |
|
D.12.4 Throwing a New Type of Error Exception |
|
|
555 | (1) |
|
D.12.5 Throwing a New Type of Exception, Derived from an Existing Thrown Type |
|
|
555 | (1) |
|
|
556 | (1) |
Glossary |
|
557 | (6) |
Index |
|
563 | |