Below is the bulk of the content from a standard procedure I recently wrote for my open source project .Mail Server Suite. Often when you have a group of people working on a single project, it makes sense to have an expectation of consistent code design from each developer. A standard procedure document is just that; a standard way of doing something. Thus many projects should develop a standard procedure document to instruct their developers on the best practice for developing in the language used. I am partial to C# in all my projects these days, and thus wrote the SP for C#. Enjoy.
C# Coding Standards
1.0 File Naming Conventions
1.1 Namespace Folders
For each namespace, a sub-folder shall exist within the main project folder with the same name as the namespace. Source files for each class that resides in the namespace shall reside in the appropriate namespace sub-folder.
1.2 C# Source Files
a. Files will be named by the class object that they implement.
b. The source file will be labeled as “ClassName.cs”
c. Classes should be given meaningful names.
d. Class names should follow UpperCamelCase naming convention with the first letter of the class in uppercase.
e. Interface class names should begin with the capital letter “I”
1.3 XML Configuration Files
a. Configuration files shall reside in either the root project folder or a designated configuration files sub-folder; e.g. \Config\
b. Configuration file names shall have the extension “.config”
c. Configuration files shall follow the XML schema standard designated by the developer.
1.4 Documentation
a. All documentation shall be written clearly and in a format designated by the Software Task Manager or designee.
b. Documentation should be stored in a format easily accessible from any machine. If rich text/content is required, the document should be stored in Microsoft Word format or Adobe Acrobat PDF format for final documents. Otherwise, documentation should be stored in a text file with standard ASCII CR-LF line breaks.
1.5 Database Scripts
a. All scripts to update related database systems shall be stored is a project sub-folder named “SQL”. Under this sub-folder, a sub-folder shall be created for the particular build version.
b. SQL script files shall be in a standard ASCII text file format with CR-LF line breaks. A script file should be created for each relevant database management system (e.g. SQL Server, mySQL, Oracle, etc.)
c. SQL script files should follow standard commenting practices as well as a standard SQL-92 format unless a specific requirement must be made for a particular database management system.
1.6 Optional Resources
a. Any additional resources such as internal resx files or images shall be stored in a sub-folder named “Resources” under the project root folder.
b. Either any files that will not be compiled or distributed should reside in the Documentation sub-folder or a separate sub-folder named “Misc”.
2.0 Source Comments
All source code files shall contain a “page-level” documentation block at the top of each file and “class-level” documentation block(s) immediately above each class. Block-level comments should be liberally used throughout the code where needed.
2.1 Page-Level Comments
2.2 Class-Level Comments
This comment header will be placed above every class:
2.3 Class-Property & Method Comments
Additionally, at a minimum a summary comment header should be placed before every public property and method within a class:
2.4 Trailing Comments
Very short comments can appear on the same line as the code they describe, but should be shifted far enough to separate them from the statements. If more than one short comment appears in a block of code, they should all be indented to the same tab column. If a comment is lengthy in wording it should always be placed above the block or line of code it is describing.
| Desired – Easy associate follow comments |
| // The following code shall add two numbers // and passing the result into an integer. iResult = iNum1 + iNum2; |
| Not Acceptable – Comments can get winded and scroll off screen |
| iResult = iNum1 + iNum2; // The following code shall add two numbers... |
2.5 Single-Line Comments
Short comments can appear on a single line indented to the level of the code that follows. If a comment cannot be written in a single line, it should follow the block comment format. A blank line should precede a single-line comment.
| Desired – Easy associate follow comments |
| if (bCondition) { // and passing the result into an integer. } |
2.6 Multi-Line Comments
The // comment delimiter should be used for multi-line comments that do not precede a large block of code. To facilitate commenting out lines of code during debug and test phases of software development, the /* ... */ comment delimiters should not be used for multi-line comments unless at the beginning of a large block comment. A blank line should precede multi-line comments.
| Desired – Easy associate follow comments |
| if (bCondition) { // The following if statement will compare the // value of bar to 1 and if it’s greater then it will // execute additional code. if (bar > 1) { ... } } |
3.0 Code Layout
3.1 Code Block Indenting
a. When indenting blocks of code use a tab character or 4 spaces per sub-block of code.
b. Opening and closing parentheses should be lined up at the same indentation level.
| Desired – Easy associate brace with if statement |
| if (bEvaluate) { if (bEvaluate2 >= 1) // operators are neatly spaced { } } |
| Not Acceptable – Not easy to associate braces with if statement, no space after if |
| if(bEvaluate) { if(bEvaluate>=1){ // operators are not neatly spaced :( } } |
c. Single-line code executions do not require braces but cannot exist on the same line.
| Desired – Easy to process, can easily add more code lines in an if-result |
| if (bEvaluate) { Console.WriteLine("The value was true"); } else { Console.WriteLine("The value was false"); } |
| Acceptable – Easy to process braces, compact |
| if (bEvaluate) Console.WriteLine("The value was true"); else Console.WriteLine("The value was false"); |
| Not Acceptable – Not easy to process braces or execution |
| if (bEvaluate) { Console.WriteLine("The value was true"); } else Console.WriteLine("The value was false"); |
3.2 Statements
3.2.1 Simple Statements
Each line should contain at most only one argument.
| Desired |
| iVariable++; // Correct iVariable2++; // Correct |
| Not Acceptable |
| iVariable++; iVariable2++; // Not-Correct |
3.2.2 Compound Statements
Compound statements are statements that contain lists of statements enclosed in braces “{ statements }”.
a. The enclosed statements should be indented one more level than the compound statement.
b. The opening brace should be on a new line below the compound statement; the closing brace should be on a separate line and be indented to the the opening brace.
c. Braces are used around all statements, even single statements, when they are part of a control structure, such as an if-else or for statement. This makes it easier to add statements without accidentally introducing bugs by forgetting to add braces.
3.2.3 Return Statements
Return statements should usually only occur once and should reside at the end of a method or property call. Placing them in multiple locations in the body of methods makes code execution paths harder to follow.
| Desired – single return point, easy to process code flow |
| virtual public bool CanUserDoSomething { get { bool returnResult = true; if (evaluate) { returnResult = false; } else { } return returnResult; } } |
| Not Acceptable – multiple return points can cause confusion, possible unused code. |
| virtual public bool CanUserDoSomething { get { if (evaluate) return false; else { return true; } } } |
3.2.4 If/Else If/Else Statements
If/Else If/Else statements should use braces following the operator to delimit their block of code. Operators should be neatly separated by a single space. See 3.1.c for examples.
3.2.5 Switch Statements
A switch statement that allows one of its cases to fall through to the next case should be commented as such. A default case should always be implemented even if it contains no further statements.
3.2.6 Do/While/For Loop Statements
Do/While loop statements are similar to if-statements in that braces should be used following the operator in all cases. Use of similar indentation and brace usage should be also be adhered to. A while-statement should be used when continually looping (checking a Boolean status for break). A foreach-loop should be used on collections and arrays where an index is not required. For-loops should be used where an element index is required.
| Desired – Easy to process braces |
| while (evaluate) { ... } |
| Acceptable – Post-test loops are not desirable |
| do { ... } while (evaluate) |
| Not Acceptable – Not easy to process braces or execution |
| do { ... } while (evaluate) |
| Desired – Easy to process braces |
| foreach (string s in strings) { } |
| Acceptable – required only when index check required |
| for (int i = 0; i < strings.length; i++) { if(i == 0) { strings += "-first"; } } |
| Not Acceptable – Not easy to process, out of loop variable initialization, end of loop check lengthy |
| int l = 0; for (l;l<=strings.length-1;l++) { if(l == 0) strings[l]; } |
4.0 Declarations
4.1 Number per Line
One declaration should be placed per line as this encourages commenting.
4.2 Placement
Put declarations only at the beginning of code blocks. Don’t wait to declare variables until their first use; it can confuse a programmer and decrease code portability within the scope.
| Desired – Variables are defined early |
| void someMethod() { int intResult = 0; // begging of method block ... if (condition) { int intValue2 = 0; // beginning of if-block ... } ... } |
The one exception to this rule is indexes of for-loop, which in C# can be declared in the for-loop statement:
| Desired – index variable defined in for loop |
| for (int i = 0; i < 100; i++) { ... } |
4.3 Namespaces
Namespaces should in most cases be a name that follows a domain structure similar to a hierarchal folder structure. In fact, namespaces should correspond with the sub-folders within the project root folder. Namespace names should have their first letter capitalized followed by lowercase letters. E.g. namespace Server.Network {...}
4.4 Class and Interface Declarations
When coding C# classes and interfaces, the following formatting rules should be followed:
a. No space must exist between a method name and the parenthesis “(“ starting its parameter list.
b. The opening brace “{“ appears on the line below the declaration statement.
c. The closing brace “}” appears on a line by itself indented to match the corresponding opening brace, unless the brace is initializing an empty array property.
d. Class and interface names should use an UpperCamelCase naming convention.
e. Abbreviations should be avoided, but can be used when the meaning is clear (e.g. Url, Html, Xml, Org, etc.)
| Desired – Easy to process, braces align correctly. |
| public class CanUserDoSomething { void DoSomeMethod(...) { ... } } |
| Not Acceptable – Not easy to process braces |
| public class CanUserDoSomething { void DoSomeMethod(...) { ... } } |
4.4.1 Private Properties
a. Private property (member) variables should named using lowerCamelCase conventions.
b. Avoid abbreviations, one-character names, and non-alphanumeric characters like the underscore “_”.
4.4.2 Public Properties
a. Public property variables should be named using UpperCamelCase naming conventions.
b. In most all cases, get and set code-methods should be used for setting and retrieving a given value.
c. All public properties should be commented using the specification provided at 2.3.
| Desired – Easy to process braces, hides exposure to internal variable. |
| private string hostName; public string ReadOnlyHostName { get { return this.hostName; }
set { this.hostName = value; } } |
4.4.3 Public