Sunday, June 20, 2010

Book Review: Effective C# - Second Edition

I just finished up Effective C#: 50 Specific Ways to Improve your C# (Second Edition) by Bill Wagner.  This is a collection of expert tips presentented in a clear and concise manner.  These are targeted at the intermediate/advanced developer; it is assumed that you understand the basics of C# programming.  With that said, this is an excellent resource for folks like me.  Bill Wagner brings to light best practices, some pitfalls, and issues to consider, especially if you are designing libraries/APIs for consumption by other developers.


This is an updated version of Effective C# (First Edition) and More Effective C#.  Each of these covered different versions of the .NET framework.  This edition covers C# 4; the content is not limited to "what's new in C# 4."  It covers items that go back to the earliest versions of .NET, but also includes new items such as dynamic typing and parallel programming with PLINQ.

As the title suggests, there are 50 "items" (spread over 6 chapters).  The book is a fairly brief 300 pages; which translates into an average of 6 pages per item.  The items are well-presented with an introduction to the problem space, a recommendation (based on a set of parameters), and clearly written code snippets.  Each item is also summarized in a closing paragraph that reiterates the problem and solution.

Here's one thing that I like: Bill Wagner does not say "always do this."  Each recommendation includes the pros and cons as well as when you may want to do things one way versus another.  Many items will also refer to other items in the book.  This helps build a cohesion to the overall text.

Here's a quick listing of the chapters with a few items from each to give you an idea of the types of things covered in each:
  1. C# Language Idioms
    Item 3: Prefer the is or as Operators to Cast
    Item 5: Always Provide ToString()
    Item 8: Prefer Query Syntax to Loops
  2. .NET Resource Management
    Item 14: Minimize Duplicate Initialization Logic
    Item 15: Utilize using and try/finally for Resource Cleanup
    Item 18: Distinguish Between Value Types and Reference Types
  3. Expressing Designs in C#
    Item 22: Prefer Defining and Implementing Interfaces to Inheritance
    Item 24: Express Callbacks with Delegates
    Item 25: Implement the Event Pattern for Notifications
  4. Working with the Framework
    Item 32: Avoid ICloneable
    Item 35: Learn how PLINQ Implements Parallel Algorithms
    Item 37: Construct Parallel Algorithms with Exceptions in Mind
  5. Dynamic Programming
    Item 38: Understand the Pros and Cons of Dynamic
    Item 40: Use Dynamic for Parameters That Receive Anonymous Types
    Item 44: Minimize Dynamic Objects in Public APIs
  6. Miscellaneous
    Item 45: Minimize Boxing and Unboxing
    Item 47: Prefer the Strong Exception Guarantee
    Item 48: Prefer Safe Code
A Couple Specific Examples
Item 8: Prefer Query Syntax to Loops
Wagner takes a look at advantages that query syntax (LINQ) has over loops (for, while, do, foreach).  He doesn't say that standard loops are bad or that we should stop using them.  Instead, he shows some specific examples that illustrate how query syntax can make your code more readable and maintainable.

Personally, I've become a big fan of LINQ.  But it did take me a while to get to that point.  Wagner challenges the developer to step out of his/her comfort zone (loops) and take a look at query syntax and to consider the difference between the imperative model (telling your code how to do the task) and the declarative model (telling your code what task you want to do).

Item 14: Minimize Duplicate Initialization Logic
Wagner points out the pitfalls of having multiple constructors as part of your class and having "copy/paste" code in each of the constructors.  This seems obvious once you think about it; after all, we always strive to minimize duplicate logic.  The first tendency may be to move all of the logic into a shared private method, but Wagner points out that this is not the optimum solution.  Instead look toward having the simpler constructors (those with fewer or no parameters) call the more complex constructors (those with several parameters).

Then he goes a step further and shows specific cases where you may introduce bugs in your code if you are not careful with how you implement the shared logic.  In addition, he takes a look at the efficiency of the code generated by the C# compiler in various situations.

Overall Quality
The overall quality of the text is very good.  I did notice a few typos here and there (no one is perfect -- I'm sure you'll also find some typos in this post).  There was only one item (#23) that had what I would consider significant issues with the code samples.  Fortunately, there is a blog on the SRT Solutions (co-founded by Wagner) web site that lists the errata.  Be sure to check this out.

Tech books are notoriously hard to produce due to how quickly technology changes (especially Microsoft technologies).  The errors that I noticed were well within the tolerable range and did not distract from my understanding of the content.

I would definitely recommend this book to intermediate and advanced C# developers.  There are a number of items (especially in the dynamic and parallel items) that gave me insight into things to watch for as I look into the new features in C# 4.  As any developer advances, he/she usually ends up creating shared libraries (shared utilities, for example). Wagner includes many items that cover best practices for creating shared libraries and APIs that are consumed by other developers.  This is also helpful when one works as part of of a team on projects that have multiple interoperating assemblies/modules.

So, pick this book up.  It has bite-sized chunks of good information and some good tips on new C# features.

Happy Coding! 

No comments:

Post a Comment