2010-05-17

Review of Bill Wagner's Effective C# (2nd ed), Part 1

I had always flat-out disregarded Effective C#. I was heavily into C++ (i.e., contributing to Boost) when Effective C++ came out, and it jumped onto the "must-read" C++ shortlist. The only reason it worked, though, was because most of the smartest programmers had decades of experience with C++, so the "dark corners" of the language eventually became known. C#, in constrast, simply hasn't had that kind of adoption for so long. It is also still experiencing drastic changes (e.g., generic variance and dynamic typing in 4.0). My conclusion was that Effective C# cannot possibly be the same as "Effective C++ for C#".

Indeed, it is not. Martin Shoemaker sums it up well in his Amazon review: "Bill Wagner failed to deliver [the same] enlightenment [as Scott Meyers]. But that's a good thing..." After reading his review, I decided to read the book on its own (not expecting it to be the same as Effective C++). Besides, Bill Wagner gave me a copy, which was really nice of him.

Disclaimer: I've met Bill Wagner and heard him speak. He gave me a copy of the book for free (not even to review; just as a gift). He's also the Microsoft regional director for my region. So hopefully he won't get too mad when I point out the trouble spots along the way. :)

The book is split into 50 sections, each one addressing in detail a particular coding recommendation. In my review, I treat each section separately, with "plus" and "minus" signs for each of my responses. Since I consider myself an "intermediate" C# programmer (with Jon Skeet and Jeffrey Richter being the only known "expert" C# programmers), anything new I learned is listed as a plus.

Item 1: Use Properties Instead of Accessible Data Members

+ This is excellent advice, and Bill goes into good detail explaining why, including examples of what happens if this is not followed.

- This advice is pretty old, though. Who doesn't already know this?

- Structures used for p/Invoke interop should be mentioned as an exception to this rule.

Item 2: Prefer readonly to const

+ I had never really thought of this before, but he's right.

+ Includes a few examples where const is OK, and even required.

+ Also points out that default values for optional parameters may be implicitly const values.

Item 3: Prefer the is or as Operators to Casts

+ Clearly explains the semantic difference between is/as and casting, particularly regarding user-defined conversions (which I didn't know previously).

- Correctly points out that as-casting does not work for value types but fails to point out the easy solution of as-casting to the corresponding nullable value type.

+ Delves a bit into how foreach uses casing (again, something new I learned).

Item 4: Use Conditional Attributes Instead of #if

- The only examples given for #if usage are contract checking and tracing. The usage of #if for cross-platform compatibility (e.g., Silverlight / WPF) is ignored, though this is a perfectly valid use of #if where conditional attributes are not even a possible alternative.

- Conditional attributes are suggested instead of #if statements for contract checking, when the users should have been directed to the new Contracts support in .NET 4.

- Conditional attributes are suggested instead of #if statements for tracing, but the majority of applications would benefit from leaving tracing on in the field (controlled via app.config).

Item 5: Always Provide ToString()

+ Excellent advice that is often overlooked.

+ Also includes helpful advice regarding IFormattable.

- Minor technical error: the book states that IFormattable should accept an empty string "format" parameter, but MSDN disagrees.

2010-05-01

MS Bug: MvcBuildViews with One-Click Publish

If you set MvcBuildViews to true in your web application project file, one-click publishing (at least to the local file system) will fail with a rather obscure error message:

It is an error to use a section registered as allowDefinition='MachineToApplication' beyond application level. This error can be caused by a virtual directory not being configured as an application in IIS.

The steps to reproduce this situation (in VS2010) are as follows:

  1. File -> New Project -> ASP.NET MVC 2 Empty Web Application
  2. Right-click project file -> Unload Project
  3. Right-click project file -> Edit .csproj
  4. Change <MvcBuildViews> to true and save
  5. Right-click project file -> Reload project
  6. Create Publish Settings (File System, c:\_test, Delete all existing files prior to publish)
  7. Publish (succeeds)
  8. Publish (fails); all future Publish or Build commands will fail

There is a simple workaround: run the Clean command on the web project, and then the Publish command will work again (once).

This bug has been posted to Microsoft Connect.

Why Post It Here?

Just this morning, I realized that two critical Microsoft bugs that I was watching were quietly removed from Microsoft Connect. These are bugs that I had invested a lot of time in discovering, exploring, reproducing, and detailing. One of them was closed recently as "external," so I posted a comment asking which group I should ask about the bug. Instead of replying, both of those bugs were silently removed from the entire Microsoft Connect system.

I attempted to retrieve the detailed bug reports, which had cost me many hours of development time. Google had refreshed since my bugs were censored, so the Google cache was no help; same with Bing. The Internet Archive wasn't even able to get those pages; apparently Microsoft Connect disabled the Archive's access way back in May of 2008.

The end result: all of the hard work I had put into those bug reports is gone. Some Microsoft team probably got brownie points for reducing their bug count. And I no longer trust Microsoft Connect. From now on, I will cross-post all Microsoft bugs to my blog.

Update (2010-05-13):

After contacting Microsoft Connect technical support, my deleted bugs have been recovered. I do still plan to cross-post, however, just in case.

Russian Translation of "Implementing IDisposable and Finalizers: 3 Simple Rules"

So, I was poking around Google Analytics today just for fun, and noticed that someone translated my post "How to Implement IDisposable and Finalizers: 3 Simple Rules" into Russian. The translated article also includes each of my detailed posts.

Cool! :)