Effective C#
If you're interested in, or currently working with, .NET and are tempted to skip past this book as Just Another C# Reference Book, think again. Wagner's book is a great resource because it covers concepts which run across the entire .NET Framework regardless of which language you're working with. While this book focuses on C#, VB.NET developers can benefit from some of the text within as well.
I also think this book speaks to a wide range of readers. Seasoned developers will blow through this content, fine-tuning their coding methods or starting new ones. Wagner specifically points out how practices experienced C++ developers may use aren't good practices in C#, such as avoiding function call overhead by writing longer C# methods with more convoluted loops. More on that later.
New developers also can greatly benefit from this book by using it to properly form development habits early in their careers. Examples of this might include following Wagner's recommendations for safe casting, strong use of interfaces, and knowledgeable resource management.
Wagner's writing style is clear and concise. He occasionally comes across as brusque, or as writing only to experienced developers ("I wouldn't write code like this and neither would you."), but those instances are few and far between. The rest of the book's voice is terrific. More important is the weight of Wagner's knowledge and experience.
One real drawback is a large number of typographical errors, sometimes several per chapter. Some sentences are missing content, and there are a large number of run-together words. These errors don't take away from the material, but it's an annoyance all the same. I would have expected better proofreaders at AW.
The book is well organized into six chapters, each hitting a specific area in C#. Within each chapter, Wagner covers six to ten items, each item focusing on one specific "minitopic," as Wagner calls them. Each item includes code snippets to demonstrate recommended approaches. Few of Wagner's snippets will function as standalone programs, but this is an advantage, as I see it. The book focuses on tight, specific examples, rather than weighing itself down with pages of extraneous fluff.
Often Wagner's recommended approach is contrasted against bad practices, or practices which might be optimal in other languages but work poorly in C#. An example of this would be Chapter 4's Item 31: "Prefer Small, Simple Functions," where Wagner shows how smaller functions are generally more efficient than larger functions with complex loops. This probably confounds experienced C++ developers, but it's a prime example of how valuable this book is. Wagner shows that .NET's Just-In-Time compiler pays less cost when calling functions than it does trying to wade through convoluted loop logic. His recommendation? Write "the clearest code you can create. Let the JIT compiler do the rest."
Chapter 1, "C# Language Elements", hits hard the topics "you must remember every day when you write C# code." This chapter discusses issues central to C#'s syntax, implementation and optimization. Wagner talks about basic Object Oriented concepts such as hiding class data members behind Properties (.NET's common access methods/fields via gets and sets), and why it's important to implement a ToString() method. Basic software engineering topics are also covered, like why it's important to differentiate between value and reference data types -- and the pitfalls of failing to do so. This chapter also thrashes out coverage on deep C# concepts like why developers should use foreach loops and why the GetHashCode() method will "practically always get you in trouble."
Chapter 2, ".NET Resource Management", has a lot of text on general patterns for constructing optimal code. Wagner's in-depth knowledge of the .NET Framework's underpinnings really shows through here. There's a very clear discussion of the performance ramifications of boxing (wrapping value type data into an object for method parameters) and unboxing. Minimizing extra garbage (unnecessary objects) and easing resource clean up via standard dispose patterns are also covered. This chapter's critical to ensuring you understand what's going on with resources in your .NET application.
Chapter 3, "Expressing Designs with C#", looks at object-oriented design in C#. While the discussion's specific to C#, there's a lot of great, practical information which applies to any object oriented development. Wagner gives some great examples with backup discussion regarding preferring the use of interfaces over inheritance and why it's a cleaner solution. (Java programmers who've read Alan Holub's "Why extends is Evil" in JavaWorld would enjoy this section.) There's also great treatment of using delegates for callbacks, and events for outgoing interfaces. Wagner also points out more pitfalls in a reference data type language: returning references to internal class objects via a read-only property (getter for Java folks).
Chapter 4, "Creating Binary Components", shows what critical topics you have to consider when creating even a moderately complex system for deployment. Wagner exposes some terrific details on how smaller is better when developing .NET assemblies for deployment. He also discusses why it's best to limit a class's exposure through public scope since this ends up advertising too much of your class's internals to potential users of that class. Wagner ties this back to interface discussions in earlier portions of the book, and makes a good case in this section for bad scope's impact on deployment.
Chapter 5, "Working with the Framework", delves into the .NET Framework Class Library. The FCL is a huge library and Wagner's insistent that too many developers are writing custom code for functionality which already exists in the FCL. This section helps to avoid having "developers reinvent the wheel." There are very useful discussions on using .NET runtime diagnostics, .NET's validation capabilities, and standard configuration mechanisms. Wagner also shows why .NET's reflection capability (one component dynamically discovering another component's capabilities at runtime) can be overused - but he also shows how to best use it in the appropriate cases.
Chapter 6, "Miscellaneous", is the catch-all section. Security and exceptions are covered here, as is the pain of working with COM interoperability - and why you should avoid it if at all possible. Just as importantly, Wagner points to several tools which should be in any C# developer's belt. He also identifies terrific resources available online.
What makes this book so useful is that Wagner constantly talks about the reasons behind why specific choices in C# should be made. For example, in Item 3, "Prefer the as and is Operator to Casts" Wagner moves through the rationale of why a developer should (when possible) avoid casting in C# and use the as and is operators instead. Casting can lead to headaches with data loss when casting a long data type to an integer one, or more headaches with the extra lines of code to ensure the cast was to a proper type. Sure, casts are sometimes necessary, and it's another value point for this book that Wagner gives clear examples of when his techniques don't apply -- and he also shows recommended alternatives for those cases.
It's just this kind of discussion from an experienced developer that makes this book so valuable. Good developers need to understand the ramifications of choices they make designing and implementing a system. Wagner's book is outstanding for exactly this kind of detailed, clear exposition.
An additional bonus: Wagner has a blog dedicated to discussion of items from his book. Erata are also listed there. See Bill Wagner's Effective C# blog.
The bottom line: this book really is a critical addition to a serious C# or .NET developer's bookshelf. It deserves a place right alongside books from McConnell, Macguire, Kernighan and Pike.
You can purchase Effective C#: 50 Specific Ways to Improve Your C# from bn.com. Slashdot welcomes readers' book reviews -- to see your own review here, read the book review guidelines, then visit the submission page.
Click on this link for the blog.
Synchronize your calendar and mobile phone via text messaging.
The review is missing something important. Effective C# is of the same mold as the Scott Meyers' Effective C++ franchise - known by many C++ programmers as a great resource of best practices. Bill has Meyer's approval to publish an "Effective" book, and even announced its publication on his mailing list.
tbh, I'm not sure that that is a recommendation. We have been going over cc in a reading group at work for the better part of a year now (chapter a week takes a while!), and overall, while he does have a lot of worthwhile stuff to say, the book is mostly dross, coupled with misleading stats, poor editing (and occasionally worse writing) lack of direction and bad analogies. .net knowledge will pretty much provide that anyway)
On the other hand, it has proved useful as a talking point in our reading group (a mix of professional programmers ranging from fresh grads to seasoned vets). As for the C# book, well we could do with a good reference for the language (although a decent c++ book and a little java and
"Success is based on knowing how far to go in going too far"
But does it work on Linux?
Joke aside, that's the question I was asking myself. Why learn a platform specific language when you can use a platform independent language like C++, Java or Ruby?
Windows is wonderful (well, not really), but there are other platforms out there as well.
Take the cheese to sickbay, the doctor should see it as soon as possible - B'Elanna Torres, "Learning Curve"
Did you know you can't see patents pending? There is no databse for them, its secret until its rejected/accepted. In addition, they can send in a correction or addition to one, and it remains hidden longer, but still becomes effective as of the original submission date. So if they exist, we won't know for another 3 years if MS doesn't want us to.
And before you say its an ECMA standard- ECMA does not require standards to be unencumbered, or even to be licensed on a RAND basis.
I still have more fans than freaks. WTF is wrong with you people?
Take a look at this:
Sapir-Whorf and programming languages
There are also tons of other problems I have run into with the .Net framework over the last few years. Here is a _major_ problem for me that I just posted about.
If Tyranny and Oppression come to this land,
it will be in the guise of fighting a foreign enemy. -James Madison
take a guess... shared source of course. Look for a post above this one in this same thread, that I wrote explaining the consequences of the Rotor release by MS. It's just so that they can have a valid argument about code theft when Mono gets really popular...
Go hug some trees.
No, it just goes to show that Paul Graham is a very smart guy with lots of blind spots. A good design pattern does not mean that there's unecessary redundancy in the code; it means that you've applied a proven solution to a known problem (better yet, a proven, matching series of solutions, with known side effects, to a problem). One of those solutions may well be to use Lisp - that solves a certain set of problems, and creates others.
;)
If you want to really understand design patterns, there's really no way around reading Alexander himself. Or Richard Gabriel's "Patterns of Software". Or, ideally, all of them
no taxation without representation!
If MS came through with a standards compliant mode you will see a true nightmare. Since neither IE, opera, netscape or firefox come anywhere near to being standards compliant. So basically your solution is to break it for everyone instead of just a few.