C# Coding Standards for .NET

.

C#

Coding Standards for .NET

 

 

Camel Case

A word with the first letter lowercase, and the first letter of each subsequent word-part capitalized.

Example: customerName

 

Magic Number

Any numeric literal used within an expression (or to initialize a variable) that does not have an obvious or wellknown

meaning. This usually excludes the integers 0 or 1 and any other numeric equivalent precision that

evaluates as zero.

 

Pascal Case

A word with the first letter capitalized, and the first letter of each subsequent word-part capitalized.

Example: CustomerName

 

 [C#v2+]A flag to identify rules and statements that apply only to C# Language Specification v2.0 or greater.

 

Naming Conventions

“c” = camelCase

“P” = PascalCase

“_” = Prefix with _Underscore

x= Not Applicable.

 

Code Style

Source Files One Namespace per file and one class per file.

Curly Braces On new line. Always use braces when optional.

Indention Use tabs with size of 4.

Comments Use // or /// but not /* … */ and do not flowerbox.

Variables One variable per declaration.

 

Enums Avoid changing default type. Pascal Case (both the Type and the Options).

 

Properties Never prefix with Get or Set.

 

Methods Use a maximum of 7 parameters.

base and this Use only in constructors or within an override.

 

Ternary conditions Avoid complex conditions.

 

foreach statements Do not modify enumerated items within a foreach statement.

 

Conditionals Avoid evaluating Boolean conditions against true or false.

No embedded assignment.

Avoid embedded method invocation.

 

Exceptions Do not use exceptions for flow control.

Use throw; not throw e; when re-throwing.

Only catch what you can handle.

Use validation to avoid exceptions.

Derive from Execption not ApplicationException.

 

Events Always check for null before invoking.

 

Project File Pascal Case.

 

Field

(Public, Protected,

or Internal)

Pascal Case.

Avoid using non-private Fields!

Use Properties instead.

 

Constant or Static Field

Treat like a Field.

Choose appropriate Field access-modifier above.

 

Formatting

  • Never declare more than 1 namespace per file.
  • Avoid putting multiple classes in a single file.
  • Always place curly braces ({ and }) on a new line.
  • Always use curly braces ({ and }) in conditional statements.
  • Always use a Tab & Indention size of 4.
  • Declare each variable independently – not in the same statement.
  • Place namespace “using” statements together at the top of file. Group .NET namespaces above custom
  • Group internal class implementation by type in the following order:
  1. Member variables.
  2. Constructors & Finalizers.
  3. Nested Enums, Structs, and Classes.
  4. Properties
  5. Methods
  • Sequence declarations within type groups based upon access modifier and visibility:
  1. Public
  2. Protected
  3. Internal
  4. Private
  • Segregate interface Implementation by using #region
  • Append folder-name to namespace for source files within sub-folders.
  • Recursively indent all code blocks contained within braces.
  • Use white space (CR/LF, Tabs, etc) liberally to separate and organize code.

 

 

All comments should be written in the same language, be grammatically correct, and contain appropriate

punctuation.

Use // or /// but never /* … */

Do not “flowerbox” comment blocks.

Example:

// ***************************************

// Comment block

// ***************************************

Use inline-comments to explain assumptions, known issues, and algorithm insights.

Do not use inline-comments to explain obvious code. Well written code is self documenting.

Only use comments for bad code to say “fix this code” – otherwise remove, or rewrite the code!

Include comments using Task-List keyword flags to allow comment-filtering.

Example:

// TODO: Place Database Code Here

// UNDONE: Removed P\Invoke Call due to errors

// HACK: Temporary fix until able to refactor

Always apply C# comment-blocks (///) to public, protected, and internal declarations.

Only use C# comment-blocks for documenting the API.

Always include <summary> comments. Include <param>, <return>, and <exception> comment

sections where applicable.

Include <see cref=””/> and <seeAlso cref=””/> where possible.

 

 

Variables & Types

  • Try to initialize variables where you declare them.
  • Always choose the simplest data type, list, or object required.
  • Always use the built-in C# data type aliases, not the .NET common type system (CTS).
  • Only declare member variables as private. Use properties to provide access to them with public,

protected, or internal access modifiers.

  • Try to use int for any non-fractional numeric values that will fit the int datatype – even variables for nonnegative numbers.
  • Only use long for variables potentially containing values too large for an int.
  • Try to use double for fractional numbers to ensure decimal precision in calculations.
  • Only use float for fractional numbers that will not fit double or decimal.
  • Avoid using float unless you fully understand the implications upon any calculations.
  • Try to use decimal when fractional numbers must be rounded to a fixed precision for calculations. Typically this will involve money.
  • Avoid using sbyte, short, uint, and ulong unless it is for interop (P/Invoke) with native libraries.
  • Avoid specifying the type for an enum – use the default of int unless you have an explicit need for long (very uncommon).
  • Avoid using inline numeric literals (magic numbers). Instead, use a Constant or Enum.
  • Avoid declaring string literals inline. Instead use Resources, Constants, Configuration Files, Registry or other data sources.
  • Declare readonly or static readonly variables instead of constants for complex types.
  • Only declare constants for simple types.
  • Avoid direct casts. Instead, use the “as” operator and check for null.

 

Example:

object dataObject = LoadData();

DataSet ds = dataObject as DataSet;

if(ds != null)

{…}

Avoid boxing and unboxing value types.

Example:

int count = 1;

object refCount = count; // Implicitly boxed.

int newCount = (int)refCount; // Explicitly unboxed.

 

  • Try to use the “@” prefix for string literals instead of escaped strings.
  • Prefer Format() or StringBuilder over string concatenation.
  • Never concatenate strings inside a loop.
  • Do not compare strings to Empty or “” to check for empty strings. Instead, compare by using

String.Length == 0.

  • Avoid hidden string allocations within a loop. Use Compare() for case-sensitive

 

 

Flow Control

  • Avoid invoking methods within a conditional expression.
  • Avoid creating recursive methods. Use loops or nested loops instead.
  • Avoid using foreach to iterate over immutable value-type collections. E.g. String arrays.
  • Do not modify enumerated items within a foreach
  • Use the ternary conditional operator only for trivial conditions. Avoid complex or compound ternary operations.
  • Avoid assignment within conditional statements.
  • Only use switch/case statements for simple operations with parallel conditional logic.
  • Prefer nested if/else over switch/case for short conditional sequences and complex conditions.
  • Prefer polymorphism over switch/case to encapsulate and delegate complex operations.

 

Exceptions

  • Do not use try/catch blocks for flow-control.
  • Only catch exceptions that you can handle.
  • Never declare an empty catch
  • Avoid nesting a try/catch within a catch
  • Always catch the most derived exception via exception filters.
  • Order exception filters from most to least derived exception type.
  • Avoid re-throwing an exception. Allow it to bubble-up instead.
  • If re-throwing an exception, preserve the original call stack by omitting the exception argument from the throw
  • Only use the finally block to release resources from a try
  • Always use validation to avoid exceptions.
  • Always set the innerException property on thrown exceptions so the exception chain & call stack are maintained.
  • Avoid defining custom exception classes. Use existing exception classes instead.
  • When a custom exception is required;
  • Always derive from Exception not ApplicationException.
  • Always suffix exception class names with the word “Exception”.
  • Always add the SerializableAttribute to exception classes.

 

4.6 Object Composition

  • Always declare types explicitly within a namespace. Do not use the default “{global}” namespace.
  • Avoid overuse of the public access modifier. Typically fewer than 10% of your types and members will be part of a public API, unless you are writing a class library.
  • Consider using internal or private access modifiers for types and members unless you intend to support them as part of a public API.
  • Never use the protected access modifier within sealed classes unless overriding a protected member of an inherited type.
  • Avoid declaring methods with more than 5 Consider refactoring this code.
  • Try to replace large parameter-sets (> than 5 parameters) with one or more class or struct parameters – especially when used in multiple method signatures.
  • Do not use the “new” keyword on method and property declarations to hide members of a derived type.
  • Only use the “base” keyword when invoking a base class constructor or base implementation within an override.
  • Consider using method overloading instead of the params attribute (but be careful not to break CLS Compliance of your API’s).
  • Wrap instantiation of IDisposable objects with a “using” statement to ensure that Dispose() is

automatically called.

Example:

using(SqlConnection con = new SqlConnection(_connectionString))

{…}

 

Object Model & API Design

  1. Always prefer aggregation over inheritance.
  2. Avoid “Premature Generalization”. Create abstractions only when the intent is understood.
  3. Do the simplest thing that works, then refactor when necessary.
  4. Always make object-behavior transparent to API consumers.
  5. Avoid unexpected side-affects when properties, methods, and constructors are invoked.
  6. Always separate presentation layer from business logic.
  7. Always prefer interfaces over abstract classes.
  8. Try to include the design-pattern names such as “Bridge”, “Adapter”, or “Factory” as a suffix to class names where appropriate.
  9. Only make members virtual if they are designed and tested for extensibility.
  10. Refactor often!

 

Add a Comment

Your email address will not be published. Required fields are marked *