Table of Contents
| Ch. 1 | C# language elements | 1 |
| Ch. 2 | .NET resource management | 77 |
| Ch. 3 | Expressing designs with C# | 117 |
| Ch. 4 | Creating binary components | 177 |
| Ch. 5 | Working with the framework | 205 |
| Ch. 6 | Miscellaneous | 265 |
Forewords & Introductions
This book is designed to offer practical advice for the programmer on how to improve productivity when using the C# language and the .NET libraries. In it, I have comprised 50 key items, or minitopics, related to the most-frequently-asked questions that I (and other C# consultants) have encountered while working with the C# community.
I started using C# after more than 10 years of C++ development, and it seems that many C# developers are following suit. Throughout the book, I discuss where following C++ practices may cause problems in using C#. Other C# developers are coming to the language with a strong Java background; they may find some of these passages rather obvious. Because some of the best practices change from Java to C#, I encourage Java developers to pay special attention to the discussions on value types (see Chapter 1, "C# Language Elements"). In addition, the .NET Garbage Collector behaves differently than the JVM Garbage Collector (see Chapter 2, ".NET Resource Management").
The items in this book are the collection of recommendations that I most often give developers. Although not all items are universal, most of the items can be easily applied to everyday programming scenarios. These include discussions on Properties (Item 1), Conditional Compilation (Item 4), Immutable Types (Item 7), Equality (Item 9), ICloneable (Item 27), and the new Modifier (Item 29). It has been my experience that, in most situations, decreasing development time and writing good code are the primary goals of the programmer. Certain scientific and engineering applications may place the highest premium on the overall performance of the system. Still, for others, it's all about thescalability. Depending on your goals, you might find particular information more (or less) relevant under certain circumstances. To address this, I have tried to explain the goals in detail. My discussions on readonly and const (Item 2), Serializable Types (Item 25), CLS Compliance (Item 31), Web Methods (Item 34), and DataSets (Item 41) assume certain design goals. Those goals are spelled out in these items, so that you can decide what is most applicable for you in your given situation.
Although each item in Effective C# stands alone, it is important to understand that the items have been organized around major topics, such as C# language syntax, resource management, and object and component design. This is no accident. My goal is to maximize learning the material covered in the book by leveraging and building each item on earlier items. Don't let that keep you from using it as a reference, though. If you have specific questions, this book functions well as the ideal "ask-me" tool. Please keep in mind that this is not a tutorial or a guide to the language, nor is it going to teach you C# syntax or structure. My goal is to provide guidance on the best constructs to use in different situations. Who Should Read this Book?
Effective C# is written for professional developers, those programmers who use C# in their daily work lives. It assumes that you have some experience with object-oriented programming and at least one language in the C family: C, C++, C#, or Java. Developers with a Visual Basic 6 background should be familiar with both the C# syntax and object-oriented design before reading this book. Additionally, you should have some experience with the major areas of .NET: Web Services, ADO.NET, Web forms, and Windows Forms. I reference these concepts throughout the book.
To fully take advantage of this book, you should understand the way the .NET environment handles assemblies, the Microsoft Intermediate Language (MSIL), and executable code. The C# compiler produces assemblies that contain MSIL, which I often abbreviate as IL. When an assembly is loaded, the Just In Time (JIT) Compiler converts that MSIL into machine-executable code. The C# compiler does perform some optimizations, but the JIT compiler is responsible for many more effective optimizations, such as inlining. Throughout the book, I've explained which process is involved in which optimizations. This two-step compilation process has a significant effect on which constructs perform best in different situations. About the Content
Chapter 1,"C# Language Elements," discusses the C# syntax elements and the core methods of System.Object that are part of every type you write. These are the topics that you must remember every day when you write C# code: declarations, statements, algorithms, and the System.Object interface. In addition, all the items that directly relate to the distinction between value types and reference types are in this chapter. Many items have some differences, depending on whether you are using a reference type (class) or a value type (struct). I strongly encourage you to read the discussions on value and reference types (Items 6 through 8) before reading deeper into the book.
Chapter 2, ".NET Resource Management," covers resource management with C# and .NET. You'll learn how to optimize your resource allocation and usage patterns for the .NET managed execution environment. Yes, the .NET Garbage Collector makes your life much simpler. Memory management is the environment's responsibility, not yours. But, your actions can have a big impact on how well the Garbage Collector performs for your application. And even if memory is not your problem, nonmemory resources are still your responsibility; they can be handled through IDisposable. You'll learn the best practices for resource management in .NET here.
Chapter 3, "Expressing Designs with C#," covers object-oriented design from a C# perspective. C# provides a rich palette of tools for your use. Sometimes, the same problems can be solved in many ways: using interfaces, delegates, events, or attributes and reflection. Which one you pick will have a huge impact on the future maintainability of your system. Choosing the best representation of your design will help to make it easier for the programmers using your types. The most natural representation will make your intent clearer. Your types will be easier to use and harder to misuse. The items in Chapter 3 focus on the design decisions you will make and when each C# idiom is most appropriate.
Chapter 4, "Creating Binary Components," covers components and language interoperability. You'll learn how to write components that can be consumed by other .NET languages, without sacrificing your favorite C# features. You'll also learn how to subdivide your classes into components in order to upgrade pieces of your application. You should be able to release new versions of a component without redistributing the entire application.
Chapter 5, "Working with the Framework," covers underutilized portions of the .NET Framework. I see a strong desire in many developers to create their own software rather than use what's already been built. Maybe it's the size of the .NET Framework that causes this; maybe it's that the framework is completely new. These items cover the parts of the framework where I have seen developers reinvent the wheel rather than use what they've been given. Save yourself the time by learning how to use the framework more efficiently.
Chapter 6, "Miscellaneous," finishes with items that did not fit in the other categories and with a look forward. Look here for C# 2.0 information, standards information, exception-safe code, security, and interop. A Word About the Items
My vision for these items is to provide you with clear and succinct advice for writing C# software. Some guidelines in the book are universal because they affect the correctness of a program, such as initializing data members properly (see Chapter 2). Others are not so obvious and have generated much debate in the .NET community, such as whether to use ADO.NET DataSets. While I personally believe that using them is a great timesaver (see Item 41), other professional programmers, whom I highly respect, disagree. It really depends on what you're building. My position comes from a timesaving stance. For others who write a great deal of software that transfer information between .NET- and Java-based systems, DataSets are a bad idea. Throughout the book, I support and have given justification for all the suggestions I make. If the justification does not apply to your situation, neither does the advice. When the advice is universal, I usually omit the obvious justification, which is this: Your program won't work otherwise. Regarding C# 2.0
I say little about the upcoming C# 2.0 release; there are two reasons for this. First and foremost, most of the advice in this book applies just as well for C# 2.0 as it does for the current version. Although C# 2.0 is a significant upgrade, it is built on C# 1.0 and does not invalidate most of today's advice. Where the best practices will likely change, I've noted that in the text.
The second reason is that it's too early to write the most effective uses of the new C# 2.0 features. This book is based on the experience I've hadand the experience my colleagues have hadusing C# 1.0. None of us has enough experience with the new features in C# 2.0 to know the best ways to incorporate them into our daily tasks. I'd rather not mislead you when the simple fact is that the time to cover the new C# 2.0 features in an Effective book has not yet arrived.