Purpose
The purpose of this document is to describe the C# coding standards used in the industry and my personal recommendations.
Microsoft Standards
I primarily follow the Microsoft standards and best practices for C# development. The following information should be considered as part of your companies standard:
§ C# Programming Guide (MSDN)
§ C# Reference (MSDN)
§ C# Language Specification (MSDN)
The standards listed in this blog either highlight best practices contained in the MSDN documentation above or define conventions that are not included in the MSDN documentation.
Definitions
See my previous blog post about Definitions here:
Design Guidelines
1. VisualStudio Solution, Project & Namespace Naming
§ Should reflect scope of use if use by all development team (e.g. "stroupsoftware..WebService.DataAccess")
§ Should reflect company, product and purpose (e.g. "IdhBrandedSite" or "Idh.BrandedSites.SharedControls")
2. Directory Structure/Organization
§ TFS Source Repository Directory Structure (Future Article)
§ Sub directories should indicate contents or purpose (web sites)
"Controls"
"Images"
3. Branded or Client Specific Projects
§ (more details)
§
Visual Studio Team System Configuration
§ Code Analysis
§ Code Analysis should be turned on for all projects
§ All rules should be turned on
§ "Treat Warnings as Errors" should be set for all rules
§ For existing projects that did not previously have Code Analysis enabled, rules may need to be turned on one by one in order to avoid breaking the build for long periods of time
§ Include a Code Analysis Dictionary (CodeAnalysisDictionary.xml) in each project with company terms ("StroupSoftware")
§ Sharing a common dictionary across projects can result in files outside of source control
§ Add any Error/Warning Suppressed Messages to and external Project Suppression File for each project
Referencing other Libraries
§ Only reference C# libraries that meet your Development Standards.
This can include:
A. Open source libraries that do not require licensing and can be used with or without payment.
B. Commercial libraries you have licenses for each server or desktop
This does not include any other language supported by the .Net Framework, like VB.Net or J#, etc. This does not include libraries that require a separate install on our servers that cannot be accomplished other ways.
§ Note: The problem is that the more libraries you might pull in that require an MSI or something else, the more complex it becomes to setup a web server to support your system.
Naming and Variable Conventions
Please refer to Visual Studio Team System Naming Warnings (MSDN) for a list of C# naming standards.
Directory, File & Custom Control Names:
Directory, file & custom control names should be Pascal Case.
Class Names:
Class names should be Pascal Case.
Method Names:
C# - Method names should be Pascal Case
(Java – Method names should be Camel Case)
Method names should clearly describe the action taken. A method "WriteIt();" might seem clear at first but a few weeks later it might not be clear what is happening. Does it write to the screen, or to a log, or to somewhere else. It writes "It" but why? "WritePropertiesFile();" is much clearer. When naming anything, pretend in your head to ask your grandmother or uncle what it might mean to "WriteIt();" or "WritePropertiesFile();". While they might not understand exactly what it means, WriteIt should mean very little while WritePropertiesFile at least means that calling it will write out a properties file. We know what properties files are and why we might want one. In context, WritePropertiesFile is most likely very clear.
Property Names:
Property names should be pascal case and should be a noun or noun phrase.
public int WebServiceMethodResultID { get; set; }
Variable Names:
Variable names should be Camel Case and not Hungarian Notation.
sourceDirectory = new Directory(srcDir);
Constant Variable Names:
Constant variable names should also be Camel Case and not Hungarian Notation.
private const string tabNode = "tab";
Class Scope Private Member Variable Names:
Class scope private member variables will be named starting with a underscore.
private IWidgetHost _host;
Variable length:
Variables should not be 1 or 2 characters in length. The problem with "Exception e" is that if you want to search for "e", it shows up in nearly every line of code. Even variables that are used in a limited scope should be at least 3 characters in length.
Abbreviations:
Variable names should not be abbreviated. aveScr is not as good as averageScore, compNm is not as clear as componentName. However, "pw" is a good name for a PrintWriter.
Reference Strings
1. Define as Constant within the class: If the string will never need to be changed and is only relevant to the class in question. This will keep it proximal to the code using it, whilst concentrating all the class constants in one place.
2. Define in a single class at a scope that makes sense (project/solution wide): If the string will never need to be changed and is relevant to multiple classes
3. Define in settings.settings: If the string needs to be changeable by the end user at configuration time
4. Define in the resources.resx file:
a. If the string needs to be changed based on the locale the application is running in (e.g. It contains text displayed to the user)
b. If the string sensibly fits within a grouping of configurable items that could be applied to the application (e.g. you want to be able to ’skin’ your application so that multiple configurations can be chosen)
Settings or Resource File Note:
Resources.resx file are only modifiable pre-build, the end-user will not be able to change the contents; Settings.settings files are rolled up into the application’s configuration and are therefore customizable by the end user.
Settings.settings files are not localization aware, they should not be used to make your app localizable. Resources should be used for this.
Comments
· Comments are a code smell that may indicate a problem with the code. For example if there is code that is not easily readable with a comment describing the code, perhaps the solution is to write code that can be more easily understood.
· Comments can easily get out of sync with reality. If comments are kept to a minimum, the getting out of sync problem can be avoided.
· That said, comments are not discouraged. Instead, the programmer should recognize that if comments are being used to describe the code, the programmer should look at the code and determine why the code is not easily understood and then should rewrite the code so that it is well understood. A worthwhile comment is:
// This code does blah blah blah. REFACTOR it soon to make it clearer.
Exceptions to this are when describing why certain algorithms or values are being used. For example, no one would like to see the code:
This code would wait for 30 minutes when the parameter is for thousandths of a second. Better would be
final long timeout = 30 * 60 * 1000;
wait(timeout);
The problem here is not understanding the code but knowing WHY 30 minutes instead of 10 seconds or 60 minutes. The only solution to this problem is to have a comment to describe why the timeout was chosen. Most often a clearly defined value is all that is needed. At other times, the WHY must be described in a comment? So better yet would be:
// Since it should finish in 1 to 5 minutes, 30 minutes is believed to be an acceptable timeout.
final long timeout = 30 * 60 * 1000;
wait(timeout);
NEVER use a comment to explain the obvious. For example:
// Loop 10 times. (This is a useless comment.)
for (int try = 0; try < 10; try++)
{
// Display which try we are on. This is a useless comment.
System.out.println("We are on try #" + try);
}
When adding a comment ALWAYS ask WHY? Why loop 10 times? Here the 10 is obviously a Magic Number and should be changed. That alone may describe why 10 is the max, but it may not. Only comment to explain why, not what.
XML Documentation Comments
XML Documentation Comments should be included for all public and protected members (classes, methods, properties, events, etc.). These comments are automatically inserted within the Visual Studio editor by typing three forward slashes on the line above the member to be documented.
/// <summary>
/// Description for SomeMethod.</summary>
/// <param name="s"> Parameter description for s goes here</param>
/// <seealso cref="System.String">
/// You can use the cref attribute on any tag to reference a type or member
/// and the compiler will check that the reference exists. </seealso>
public void SomeMethod(string s)
{
}
See XML Documentation Comments (MSDN) for additional on XML Documentation Comments.
Namespace Documentation Comments
All namespaces should be documented the same as classes, methods, etc. This is accomplished by the following process:
· Adding a NamespaceDoc.cs file to the project for the namespace
· Adding a NamespaceDoc class and providing XML comments for this class
· When comments for this class are found by Sandcastle, they will be used for the namespace documentation.
The following is an example of how this looks:
namespace Utilities
{
/// <summary>
/// The namespace for various global, generic gadgets used by all StroupSoftware web portals.
/// These gadgets cover general operations such as printing, pop-ups and others.
/// </summary>
[System.Runtime.CompilerServices.CompilerGenerated]
class NamespaceDoc
{
}
}
Zero Tolerance to Warnings Policy
You should have a policy of “Zero Tolerance to Warnings”.
What does that mean? That means that the Output tab should look like this: 
When the project Code Analysis tab looks like this:

And the Build tab includes the generation of the “XML documentation file” like this:

The goal is Zero Warnings.
Approved Warning Suppressions
While trying to achieve Zero Tolerance to Warnings you will encounter warnings whose only appropriate resolution is suppression. In those cases those suppression's should be in the Global Suppression File (GlobalSuppressions.cs) for the project.
Here is the list of some approved suppressions:
· CA1014 Microsoft.Design "Mark Assemblies With Cls Compliant"
· CA2210 Microsoft.Design "Assemblies Should Have Valid Strong Names"
Indentation
Use the default VisualStudio Tab and Indent size of 4 spaces. Indenting using tabs instead of spaces will allow people to view the indentation any way they wish. In order for tabs to line up inside a line, a tab setting of 4 is required. It isn't required that everyone use a tab setting of 4, but it is the standard at which tabs inside a line will be aligned with each other.
public static final int INSTALLABILITY_UNKNOWN = 0
public static final int INSTALLABILITY_CANNOT_INSTALL = 1
public static final int INSTALLABILITY_CAN_INSTALL = 2
public static final int INSTALLABILITY_UPTODATE = 3
Curly Braces
Curly braces should be used more often than not. Over use is better than under use. Complex if statements are more easily read with the full use of curly braces. Adding additional statements are easily added. For example:
if (result.equals(RESULT_SUCCESS))
{
Some code here;
Some new line easily added here;
}
else if (result.equals(RESULT_FAIL))
{
Some code here;
}
Exception Handling
Only use "finally" to close resources in the try. In the "finally", assume the resource needs to be closed and allow the exception to handle the outside chance that the resource was not opened. This exception will most likely never be called so why add all the checking such as
Instead use the try/catch to handle the exception.
finally
{
try
{
br.close();
}
catch (throwable exc)
{
}
}
In C#, in a catch, you can just "throw;" rather than "throw(exc);" in order to preserve the original call stack. For example:
catch (Exception exc)
{
Logger.println("*** Exception while discombobulating the maniform arm.");
throw;
}
General Coding Guidelines
Things To Do
· Implement as simply as possible, then refactor as needed. Refactor often.
· Keep methods as clear and simple as possible.
· Create classes wisely.
o Use correct OO principles.
o Hide complexities inside classes.
o Make class variables private and use methods to get/set them.
· Use enums where possible. Avoid specifying "int" when using enums.
Things To Avoid
-
Use var type in your variable declaration. Implicit (or weakly typed) variables are confusing and require additional detective work for subsequent developers who look at your code. Developers need to explicitly declare the type of the variable.
-
Being overly terse when naming; instead, error on the side of verbosity.
-
Assignment during conditionals.
-
Directory structures deeper than four levels deep.
-
Lengthy names (descriptive yet concise).
-
Names that resemble keywords.
-
Using spaces for indentation.
-
Cramming logical groups of code together; instead, use blank lines between them.
-
Random distribution of private member variables, properties, and methods.
-
Writing very long methods; a method should typically have 1~25 lines of code.
-
Combining more than one "job" in a single method, even if those jobs are very small.
-
Hardcoding numbers; instead, use constants in a config file.
-
Hardcoding strings; instead, use resource files.
-
Comparing "" to a string; instead, use Sting.Empty to compare against a string.
-
Using numbers or strings to indicate discrete values; use an enum instead.
-
Making class member variables public or protected; instead, keep them private and expose public/protected Properties.
-
Having more than one class in a single file.
-
Passing too many parameters to a method. If you have more than 4~5 parameters, it is a good candidate to define a class or structure.
-
Returning null for methods with a return type that is a collection; return an empty collection instead.
-
Using the String object when you have to manipulate string objects in a loop; use StringBuilder instead.
-
Storing large objects in the Session. This may consume a lot of server memory.
-
Catching an exception and doing nothing. Always code for exceptions. At the very least, log the exception and proceed.
-
Catching an exception generically; always catch only specific exceptions.
-
Throwing an exception specifying the original exception; instead, use throw to preserve the original call stack.
0a607501-16cb-4f82-8bc4-f6b60a9d1764|2|5.0
C# Development