I just finished reading Effective C#: 50 Specific Ways to Improve Your C# by Bill Wagner, and thought I’d cover it a bit here. On the whole, I thought that this was an excellent book. It’s quite helpful and interesting, and it provides a nice counterpoint to many technical books in that you have immediate results and feedback by reading a given section. In other words, many technical books tend to be a journey that improves your situation holistically when you’ve finished it whereas this book has a bunch of helpful information that is generally autonomous. You can flip to item 20, read about it, and experience a positive result.
So, here is my take, in itemized fashion:
The Good/Don’t Miss
- Always provide ToString(): An excellent explanation of how the framework handles the ubiquitous casts of objects to strings.
- Understand the Relationships Among the Many Concepts of Equality: Wagner does a great job of breaking down the (confusing) way C# handles various notions of equality.
- Prefer Query Syntax To Loops: Get on board with declarative syntax and small, scalable methods
- Understand the Attraction of Small Functions: Excellent ammunition for arguments with people who say that it’s good to have giant, C-style methods for the sake of efficiency — don’t miss this section!
- Express Callbacks with Delegates: A nice explanation of the concept of delegates and why they’re useful.
- Avoid Returning References to Internal Class Objects: Some of the choices made by the C# language authors make this tough, but Wagner provides some elegant ways to preserve your object’s encapsulation of its internals.
- Avoid ICloneable: Glad that he points this out unequivocally. Not every language concept turns out to be advisable.
- The entire Dynamic Types section: Might be a little fast-paced as an introduction, but if you haven’t seen this new feature of C# as of V4.0, this is worth reading and making sure to understand, even if it takes a few reads.
The Questionable (in my opinion)
There was little to find objectionable in this book, but the main quibble that I did have was with “Item 25: Implement the Event Pattern for Notifications.” This example features a how-to of using events, which I think should be used perhaps more sparingly than others do, but I didn’t find this questionable in and of itself. What bothered me was that the example of an event source was some kind of global logging singleton.
To me, the use of a singleton on its own is undesirable, much less one that provides hooks for events. A singleton that fires events is a memory leak waiting to happen (because event listeners are withheld from garbage collection by the event source for the event source’s lifetime unless explicitly unhooked). The whole concept of coding up some singleton (global variable) that fires events makes me extremely leery, as you’re providing two layers of indirection with hidden dependencies: (1) singletons couple your classes with hidden dependencies just by existing and being used; and (2) events are non-obvious sources of dependency, with or without global variables.
I understand that, as an example, this is easy to wrap your head around, but people tend to copy such examples and work them into what they do, and I sure wouldn’t want to open up some code I was tasked with maintaining to find that thing.
The Rather Obvious
There’s nothing wrong with pointing out the obvious (someone needs to for the sake of beginners), so don’t take this as a knock on the contents. I’m just mentioning these here in case you’re already familiar with good OOP design practice, as you might want to skim/skip these sections.
- Use Properties instead of Accessible Data Members
- Minimize Duplicate Initialization Logic
- Limit Visibility of your Types
Who Should Read This
Really, I’d say that anyone who codes in C# should give this a read. Whether you’re new to the language or an old pro, it’s almost certain that you’ll find something new and helpful in here. It’s up to date with the bleeding edge of language idioms and it addresses some things that have been around a while. It also provides a lot of history within the language and context for things (rather than just instructing you to “do this” or “avoid that”), so it is quite approachable for a range of experience levels.