The all new coding guidelines for C# 3.0, 4.0 and 5.0 have been published!

Edit this page | 4 minute read

After 50000 downloads and the recent final release of Visual Studio 2012 / C# 5.0 it was about time to do a thorough update of the C# Coding Guidelines. Although most of the guidelines have been preserved, I’ve tried to rewrite several of them using a less formal and less verbose writing style. I’ve also improved the rational for some of them, shortened the introduction section, but added a refactoring heuristic I picked up from this blog post.

Other minor improvements include getting rid of the vague term identifier, applying the correct usage of the terms arguments and parameters, adding more cross-references between guidelines and adding various links to relevant articles. On the esthetic side, I’ve changed all code snippets to Consolas, reduced the line-spacing a bit, and changed the accent color to allow this version to stand out more from previous versions.

So which guidelines were changed?

  • Added a warning to AV1001 “Only create a constructor that returns a useful object” about potentially violating AV1000 and AV1561.
  • AV1008 “Mark classes that only contain static members as static” now promotes avoiding static classes at all rather than just marking it as static.
  • Added a reference to the Command Query Separation principle to AV1105 “Use a method instead of a property”.
  • Added a reference to the new .NET 4.5 read-only collection interfaces to AV1130 “Return an IEnumerable<T> or ICollection<T> instead of a concrete collection class”.
  • Renamed AV1135 “String, list and collection properties should never return a null reference” to include methods and parameters in addition to properties
  • Rephrased AV1140 “Consider replacing properties using primitive types to use rich value objects” to clarify that I was talking about domain-specific types.
  • Remove the incorrect examples from AV1515 “Don’t use "magic” numbers”
  • Renamed AV1521 “Initialize variables at the point of declaration” to make it clear we want variables to be declared and initialized as a late as possible.
  • Removed the 'method' part of AV1532 “Don’t use nested loops in a method” to say that nested loops should be avoid everywhere.
  • Renamed AV1535 “Add a block after all flow control keywords, even if it is empty” so that it includes concrete keywords rather than the vague 'flow control keywords'
  • Added a reference to AV1553 “Only use optional parameters to replace overloads” about Eric Lippert’s post on optional parameter corner cases.
  • Removed an example from AV1720 “Name methods using verb-object pair” because it conflicted with some of the LINQ extension methods introduced in .NET 3.0.
  • Rewrote and renamed AV1725 “Name namespaces according a well-defined pattern” to clearly explain the valid aspects of a namespace rather than emphasizing a particular pattern.
  • Changed the example in AV1735 “Use a verb or verb phrase to name an event” to use a generic event handler delegate.
  • Added a reference to to the .NET 4.5 read-only collection classes to AV1800 “Consider using Any() to determine whether an IEnumerable<T> is empty”. 
  • Added a statement to AV2207 “Don’t hardcode strings that change based on the deployment” that deployment-specific settings should be in the application configuration files rather than hard-coded or in a custom configuration file.
  • Added a remark to AV2400 “Use a common layout” not to interweave the from expressions with where conditions.

And what did I add?
The following guidelines have been added, of which, for obviously reasons, most are related to C# 5.0.

  • Added AV1137 "Define parameters as specific as possible" to prevent people from passing in entire objects even though a method might only need a specific property’s value.
  • Added AV1215 "Properly handle exceptions in asynchronous code" to explain the differences between exceptions raised in Actions and await blocks.
  • Added AV1523 "Initialize each variable on a separate line" to prevent some ugly code.
  • Added AV1739 "Use an underscore for irrelevant lamba parameters" as suggested by James Lanng.
  • Added AV1755 "Postfix asynchronous methods with Async of TaskAsync"
  • Added AV1820 "Only use async for low-impact long-running activities"
  • Added AV1825 "Prefer Task.Run for CPU intensive activities"
  • Added AV1830 "Beware of mixing up await/async with Task.Wait"
  • Added AV1835 "Beware of async/await deadlocks in single-threaded environments"

    “But wait, didn’t you remove anything?”
    Of course I did! Why do you think the number of pages went from 31 to 27? Well, yes, reducing line-spacing was part of that, but I actually did remove some guidelines.

    • Removed AV1120 "Use a public static readonly field to define predefined value objects " since I think it is not that important and not used very often.
    • Removed AV1245 “Don’t add extension methods to the same namespace as the extended class” because I think it is pretty farfetched if you create a class in a .NET namespace.
    • Removed AV1526 “Use an enumeration instead of a list of strings if the list of values is finite” since enumerations are so common these days, I hope nobody thinks of an alternative solution.
    • Merged AV1546 “Prefer conditional statements instead of simple if-else constructs” into AV1545 “Don’t use selection statements instead of a simple assignment or initialization”.
    • Removed AV1580 “Consider abstracting an external dependency or 3rd party component” because its essence is already covered by other guidelines and the introduction discussing SOLID principles.  
    • Removed AV2211 “Avoid suppressing specific compiler warnings” since I wonder how many developers even know how to suppress compiler warnings.
    • Removed AV2315 “Don’t use /* */ for comments” since we want to avoid inline comments anyhow.

    You can download the PDFs of the document itself, the cheat sheet, the Visual Studio 2010/2012 Code Analysis rule sets, and the ReSharper 6/7 Code Analysis settings from the download page on the CodePlex landing page.

    And don’t forget! If you have any feedback, additions or any remarks, contact me through Twitter or email.

    Leave a Comment