C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines...

49
C# Coding Guidelines and Best Practices Pradeep Kumar Mishra Page 1 Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra

Transcript of C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines...

Page 1: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 1

Dot Net Development Open Book

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra

Page 2: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 2

1 INTRODUCTION ......................................................................................... 4

2 NAMING CONVENTIONS AND STYLE ................................................................. 4

2.1 Capitalization style ........................................................................... 4

2.1.1 Pascal case .................................................................................. 4

2.1.2 Camel case .................................................................................. 4

2.1.3 Uppercase ................................................................................... 4

2.1.4 Capitalization Summary ................................................................. 5

2.2 Naming rules................................................................................... 5

2.2.1 Namespaces ................................................................................ 6

2.2.2 Classes ....................................................................................... 6

2.2.3 Method ....................................................................................... 7

2.2.4 Interfaces .................................................................................... 7

2.2.5 Enums ........................................................................................ 8

2.2.6 Static Fields ................................................................................. 9

2.2.7 Variables ..................................................................................... 9

2.2.8 Properties .................................................................................. 10

2.2.9 Events ...................................................................................... 11

2.2.10 Case sensitivity ....................................................................... 12

2.2.11 General ................................................................................. 12

3 CODING STYLE ........................................................................................ 15

3.1 Source Files .................................................................................. 15

3.2 Ordering ....................................................................................... 15

3.3 Indentation ................................................................................... 15

3.3.1 Wrapping Lines .......................................................................... 15

3.3.2 White Spaces ............................................................................. 15

3.4 Comments .................................................................................... 16

3.4.1 Implementation Comments .......................................................... 16

3.4.2 Documentation Comments ........................................................... 18

3.4.3 Comment Tokens ........................................................................ 18

3.5 Formatting .................................................................................... 19

3.6 Declaration ................................................................................... 19

3.6.1 Number of Declarations per Line ................................................... 19

3.6.2 Initialization ............................................................................... 19

3.6.3 Class and Interface Declarations ................................................... 19

3.7 Statements ................................................................................... 20

Page 3: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 3

3.7.1 Simple Statements ..................................................................... 20

3.7.2 Return Statements ...................................................................... 20

3.7.3 If, if-else, if else-if else Statements ............................................... 20

3.7.4 For / Foreach Statements ............................................................. 21

3.7.5 While/do-while Statements ........................................................... 22

3.7.6 Switch Statements ...................................................................... 22

3.7.7 Try-catch Statements .................................................................. 23

4 BEST PRACTICES ..................................................................................... 23

4.1 Performance ................................................................................. 24

4.2 Usage .......................................................................................... 28

4.3 Design ......................................................................................... 32

4.4 Globalization ................................................................................. 37

4.5 Security ....................................................................................... 38

4.6 Interoperability .............................................................................. 42

4.7 Exceptions .................................................................................... 44

5 PROJECT SETTINGS AND STRUCTURE ............................................................. 46

6 REFERENCES: ......................................................................................... 48

APPNEDIX A ............................................................................................... 49

Page 4: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 4

1 Introduction

Quality has its own value in a software product development. The simplest method

for guaranteeing that a crew of the developers furnishes high quality deliverables is

to establish a coding standard. A comprehensive coding standard is essential for a

successful product delivery. It‟s not just the delivery but also the after delivery tasks

like support gets impacted by coding standards followed by the development team.

The standard helps in enforcing best practices and avoiding pitfalls and makes

knowledge dissemination across team easier.

A comprehensive coding standard encompasses all aspects of code construction and,

while developers should exercise prudence in its implementation, it should be closely

followed. Completed source code should reflect a harmonized style, as if a single

developer wrote the code in one session.

2 Naming conventions and style

2.1 Capitalization style

Use the following three conventions for capitalizing identifiers:

2.1.1 Pascal case

The first letter in the identifier and the first letter of each subsequent concatenated

word are capitalized. You can use Pascal case for identifiers of three or more

characters. For example: BackColor.

2.1.2 Camel case

The first letter of an identifier is lowercase and the first letter of each subsequent

concatenated word is capitalized. For example: backColor.

2.1.3 Uppercase

All letters in the identifier are capitalized. Use this convention only for identifiers that

consist of two or fewer letters. For example: System.IO, System.Web.UI.

Page 5: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 5

2.1.4 Capitalization Summary

Identifier Rules for Naming Notes/Examples

Class Pascal Case

Attribute Class Pascal Case Has a suffix of Attribute

Exception Class Pascal Case Has a suffix of Exception

Constant Pascal Case

Enum type Pascal Case

Enum values Pascal Case

Event Pascal Case

Interface Pascal Case Has a prefix of I

Local variable Camel Case

Method Pascal Case

Namespace Pascal Case

Property Pascal Case

Public Instance Field Pascal Case Rarely used (use a

property instead)

Protected Instance Field Camel Case Rarely used (use a

property instead)

Parameter Camel Case

2.2 Naming rules

Naming rules make programs more comprehensible by facilitating them for reading.

They can also give information about the function of the identifier, for example,

whether it's a constant, package, or class, which can be helpful in understanding the

code.

How the various elements of the application are named is perhaps the most

influential aids to understand the logical flow of an application is how the various

elements of the application are named. A name should tell "what" rather than "how."

By avoiding names that expose the underlying implementation, which can change,

you preserve a layer of abstraction that simplifies the complexity. For example, you

could use GetNextOrder() instead of GetNextArrayElement().

A tenet of naming is that difficulty in selecting a proper name may indicate that you

need to further analyze or define the purpose of an item. Let names be long enough

meaningfully however short enough avoid being wordy. Programmatically, a unique

name serves only to differentiate one item from another. Expressive names function

as an aid to the human reader; therefore, it makes sense to provide a name that the

human reader can comprehend. However, be certain that the names chosen are in

compliance with the applicable rules and standards.

Page 6: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 6

Most of the content of the naming rules has been taken from Microsoft

recommendations (link of the same has been given in the reference section).

There is a widely accepted code analyzer tool called FxCop (See reference section)

which also provide some guidelines. So if appropriate naming standards are not

defined in this document the FxCop Naming Rules should be used.

2.2.1 Namespaces

The general rule for namespace naming is:

[<Company Name>].[<Product | Technology Name>].[<Feature

Name>].[<SubNameSpace>]

Example:

Company.ProductName.Ecommerce.DataLayer;

Do avoid the possibility of two published namespaces having the same name.

Do not use department or project name as they change too frequently.

Do use Pascal Case and Nouns.

Do not use the underscore (“_”).

Do consider wider scope modules across an enterprise

Example: Company.ProductName.Core or Company.Core

Do use whole, simple and descriptive words and avoid acronyms and

abbreviations unless abbreviation is much more widely used than long form,

such as URL, Xml etc.

Do use plural namespace names where appropriate. For example, use

System.Collections rather than System.Collection. Exceptions to this rule are

brand names and abbreviations. For example, use System.IO not System.IOs.

Do not have namespaces and classes with the same name.

2.2.2 Classes

Do name classes with nouns or noun phrases using Pascal Case. Names may

start with an adjective, but should always end with a descriptive noun or noun

phrase (User, CustomUser or ReadonlyUser).

Do use sparingly, abbreviations in class names.

Do not use plural tense, use a second descriptive noun, or noun phrase

instead (UserCollection instead of Users)

Do not use any prefix (such as “C”, for example). Where possible, avoid

starting with the letter “I”, since that is the recommended prefix for interface

names. If you must start with that letter, make sure the second character is

lowercase, as in IdentityStore.

Do use suffixes at times. For example, if your system uses agents then

naming something DownloadAgent conveys real information.

Do not bring the name of the class that the class derives from into the

derived class's name (However there are some special cases mentioned

later). A class should stand on its own. It doesn't matter what it derives from.

Page 7: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 7

Do not use any underscores.

Do use suffix „Exception‟ with custom exception class.

e.g. public class NoDataFoundException{ .. }

Do use suffix „Attribute‟ with custom attribute class.

e.g public class PersistentEntityAttribute

Do add the suffix Stream to types that inherit from System.IO.Stream.

Example:

public class InvoiceItemGroup { … }

public class Invoice { … }

2.2.3 Method

Do name methods with Pascal Case

Do name methods with active verb forms and imperatives (ProcessInvoice,

SubmitTransaction). It is not necessary to include the noun name when the

active verb refers directly to the containing class.

Example:

Invoice.ProcessInvoice();

// AVOID! No need to mention “Invoice” in name

Invoice.Process(); // PREFER

Do Use the verb-noun method for naming routines that perform some

operation on a given object which describes the operation, such as CalculateInvoiceTotal().

Do Not use elusive name like Analyze().

2.2.4 Interfaces

Do prefix interface names with the letter “I”, to indicate that the type is an

interface.

Do name interfaces with nouns or noun phrases, or adjectives describing

behavior (what the implementation will be.). For example, IComponent

(descriptive noun), ICustomAttributeProvider (noun phrase), and IPersistable

(adjective).

Do use Pascal Case.

Do use sparingly, abbreviations in interface names.

Do not use plural tense (IComponentCollection instead of IComponents)

Do not use any underscores.

Do use similar names when defining a class/interface pair where the class is a

standard implementation of the interface. The names should differ only by the

Page 8: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 8

“I” prefix in the interface name. This approach is used for the interface

IComponent and its standard implementation, Component.

Example:

public interface IComponent { … }

public class Component : IComponent { … }

public interface IServiceProvider{ … }

public interface IFormatable { … }

2.2.5 Enums

Do use Pascal Case for enums.

Do use Pascal Case for enum value names.

Do use sparingly, abbreviations in enum names.

Do not use a family-name prefix on enum.

Do not use any “Enum” suffix on enum types.

Do use a singular name for enums

Do use a plural name for enumerations with bit fields as values also called

flags enumerations.

SearchOptions(bitwise flags)

Do define enumerated values using an enum if they are used in a parameter

or property. This gives development tools a chance at knowing the possible

values for a property or parameter.

public enum TransactionType

{

Inquiry,

Sale,

Credit,

Authorization,

Capture,

Void

}

Do use the Flags custom attribute if the numeric values are meant to be

bitwise OR-ed together

[Flags]

public enum Bindings

{

CreateInstance,

DefaultBinding,

ExcatBinding,

GetField,

GetProperty,

IgnoreCase,

InvokeMethod,

NonPublic,

OABinding,

SetField

Page 9: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 9

SetProperty,

Static

}

Do use int as the underlying type of an enum. (An exception to this rule is if

the enum represents flags and there are more than 32 flags, or the enum

may grow to that many flags in the future, or the type needs to be different

from int for backward compatibility.)

Do use enums only if the value can be completely expressed as a set of bit

flags. Do not use enums for open sets (such as operating system version).

2.2.6 Static Fields

Do name static members with nouns, noun phrases, or abbreviations for

nouns.

Do name static members using Pascal Case.

Do not use Hungarian-type prefixes on static member names (Definition of

Hungarian notation is given in the Appendix A.)

2.2.7 Variables

Do use descriptive names such that a variable‟s name that clearly indicates

what the purpose of the variable is and what value it will hold.

Do name variables using camel case.

Do initialize variables at the point of declaration if possible.

Do prefix private fields with an underscore (“_”) like _privateField. All other

variable must follow simply camel Case.

Do prefer names based on a parameter‟s meaning, to names based on the

parameter‟s type. It is likely that development tools will provide the

information about type in a convenient way, so the parameter name can be

put to better use describing semantics rather than type.

Do use the “this” keyword when referring to members at a class‟s root scope

from within a lower level scope, as in this.name.

Do not reserve parameters for future use. If more data is need in the next

version, a new overload can be added.

Do use computation qualifiers (avg, sum, min, max, index) as prefix and

suffix of a variable name where appropriate.

Do use “is” for boolean variable which implies Yes/No or True/False values,

such as isFound, or isSuccess.

Do name Collections as the plural form of the singular objects that the

collection contains. A collection of Book objects is named Books.

Do not using terms such as Flag when naming status variables, which differ

from Boolean variables in that they may have more than two possible values.

Instead of orderFlag, use a more descriptive name such as orderStatus.

Page 10: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 10

Do use a meaningful name even for a short-lived variable that may appear in

only a few lines of code. Use single-letter variable names, such as i or j for

short-loop indexes only.

Do not use all uppercase with underscores between words for constants, such

as NUM_DAYS_IN_WEEK. Constants follow the same naming rules as

properties. The aforementioned constant would be named NumDaysInWeek.

Do not use Hungarian-type prefixes. (Definition of Hungarian notation is given

in the Appendix A.)

Example:

public class Person

{

private int _birthYear;

public Person(int birthYear)

{

this._birthYear = birthYear;

}

public int BirthYear

{

get{ return this._birthYear; }

set{ this._birthYear = value; }

}

public string FormatBirthYear(int totalLength)

{

string birthYearText = this._birthYear.ToString();

int yearLength = birthYearText.length;

}

}

2.2.8 Properties

Do name properties using noun or noun phrases

Do name properties with Pascal Case

Do not include class names in the name of class properties, such as

Book.BookTitle. Instead, use Book.Title. This is the case with all object-

oriented languages.

Page 11: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 11

Do consider having a property with the same name as a type. When declaring

a property with the same name as a type, also make the type of the property

be that type. In other words, the following is okay

public enum Color {...}

public class Control

{

public Color Color { get {...} set {...} }

}

but this is not

public enum Color {...}

public class Control

{

public int Color { get {...} set {...} }

}

In the latter case, it will not be possible to refer to the members of the Color

enum because Color.Xxx will be interpreted as being a member access that

first gets the value of the Color property (of type int) and then accesses a

member of that value (which would have to be an instance member of

System.Int32).

2.2.9 Events

Do name event handlers with the “EventHandler” suffix.

public delegate void MouseEventHandler(object sender,

MouseEvent e);

Do use two parameters named sender and e. The sender parameter

represents the object that raised the event, and this parameter is always of

type object, even if it is possible to employ a more specific type. The state

associated with the event is encapsulated in an instance e of an event class.

Use an appropriate and specific event class for its type.

public delegate void MouseEventHandler(object sender,

MouseEvent e);

Do name event argument classes with the “EventArgs” suffix.

public class MouseEventArgs : EventArgs

{

int x;

int y;

public MouseEventArgs(int x, int y)

{ this.x = x; this.y = y; }

public int X { get { return x; } }

public int Y { get { return y; } }

}

Do Consider naming events with a verb. Use a gerund (the "ing" form of a

verb) to create an event name that expresses the concept of pre-event, and a

past-tense verb to represent post-event. For example, a Close event that can

be canceled should have a Closing event and a Closed event.

Page 12: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 12

Do Use an „–ing‟ and „–ed‟ form to express pre-events and postevents.

Do not use a pattern like BeginXxx and EndXxx. If you want to provide

distinct events for expressing a point of time before and a point of time after

a certain occurrence such as a validation event, do not use a pattern like

BeforeValidation and AfterValidation. Instead, use a Validating and Validated

pattern.

public event ControlEventHandler ControlAdded

{

//..

}

2.2.10 Case sensitivity

Don‟t use names that require case sensitivity. Components might need to be

usable from both case-sensitive and case-insensitive languages. Since case-

insensitive languages cannot distinguish between two names within the same

context that differ only by case, components must avoid this situation.

Examples of what not to do:

Don‟t have two namespaces whose names differ only by case.

namespace ee.cummings;

namespace Ee.Cummings;

Don‟t have a method with two parameters whose names differ only by case.

void F(string a, string A)

Don‟t have a namespace with two types whose names differ only by case.

System.WinForms.Point p;

System.WinForms.POINT p;

Don‟t have a type with two methods whose names differ only by case.

void f();

void F();

2.2.11 General

Always use „US English‟.

When using Visual Studio.NET 2003 or Visual Studio.NET 2005 you can

specify code regions. Code regions are basically blocks of code that you can

collapse within the Visual Studio IDE. What code regions enable you to do is

group related pieces of code together which makes things easier to find. For

instance, I typically will group all my properties for a class within a Properties

code region.

#region P R O P E R T I E S

public string MyProp;

#endregion

Page 13: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 13

Please note that regions can be nested but they can‟t overlap the other block

statements.

Always use c# predefined types rather than the aliases in the System

namespace. For example

Use object and not Object

Use string and not String

Use int and not Int32

Avoid fully qualified name. Use the using statement instead.

All member variables should be declared at the top of a class definition.

public class MyClass

{

int _number

int _name;

public void SomeMethod()

}

Implementation details, in particular type specifications, should not be

mentioned in the name of a descriptor. This is a common trait in procedural

languages like Visual Basic where lowercase prefixes are used to encode the

data type in the name of the identifier, such as oInvoice. This approach is not

applicable to contemporary languages where the aforementioned identifier is

written simply as Invoice.

Names with semantic content are preferred to names with type specifications

(sizeOfArray instead of anInteger).

Minimize the use of abbreviations. If abbreviations are used, be consistent in

their use. An abbreviation should have only one meaning and likewise, each

abbreviated word should have only one abbreviation. For example, if using

min to abbreviate minimum, do so everywhere and do not later use it to

abbreviate minute.

When naming methods, include a description of the value being returned,

such as GetCurrentCustomerName().

Object references should be in camel case and they should be named after

their class. For example

InvoiceItemGroup invoiceItemGroup = new InvoiceItemGroup()

With the exception of zero and one, never hard code a numeric value; always

declare a constant instead. Please also note it is NOT ok to satisfy this

guideline by defining constants such as FortyTwo = 42.

Avoid using function calls in Boolean conditional statements. Assign into local

variable and check on them

bool ValidateInput()

{

….

Page 14: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 14

}

//Avoid

if(ValidateInput())

{

...

}

//Correct

bool isValidInput = ValidateInput();

if(isValidInput)

{

...

}

Do not use letters that can be mistaken for digits, and vice versa. To

create obfuscated code, use very short, meaningless names formed from

the letters O, o, l, I and the digits0 and 1. For example

bool b001 = (lo == l0) ? (I1 == 11) : (lOl != 101);

should not be written

Do not change a loop variable inside a for loop block. Updating the loop

variable within the loop body is generally considered confusing, even more

so if the loop variable is modified in more than one place.

Do not make explicit comparisons to true or false.

It is usually bad style to compare a bool-type expression to true or false.

Example: while (condition == false) // wrong; bad style

while (condition != true) // also wrong

while (((condition == true) == true) == true) // where do you

stop?

while (booleanCondition) // OK

Page 15: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 15

3 Coding Style

3.1 Source Files

Source files should contain one class per source file and name of file

should be same as class name. For example a file containing class Invoice

should have name Invoice.cs.

Consider breaking apart a file as it approaches 1500 lines.

3.2 Ordering

C# source files have the following ordering:

1. using statements

2. namespace statement

3. Class and interface declarations

Group all framework namespaces together and put custom or third party

namespaces underneath.

using System;

using System.Data;

using Company.ProductName.Core;

using Company.ProductName.Data;

3.3 Indentation

3.3.1 Wrapping Lines

When an expression will not fit on a single line, break it up according to these

general principles:

Break after a comma.

Break after an operator.

Prefer higher-level breaks to lower-level breaks.

Align the new line with the beginning of the expression at the same level on

the previous line

A good coding practice is to make the tab and space chars visible in the editor which

is used.

Example SomeMethod(longExpresssion1, longExpression2,

longExpression3)

3.3.2 White Spaces

Always use 4 spaces for indentation. Since we use Visual studio as IDE hence it‟s

better to use tabs over there. (By default tab is set to 4 spaces and this will reduce

typing.)

Page 16: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 16

3.4 Comments

C# programs can have two kinds of comments: implementation comments and

documentation comments. Implementation comments are those found in C++, which

are delimited by /*...*/, and //. Documentation comments are C# only, and are

delimited by special XML tags that can be extracted to external files for use in

system documentation.

Implementation comments are meant for commenting out code or for comments

about the particular implementation. Doc comments are meant to describe the

specification of the code, from an implementation-free perspective, to be read by

developers who might not necessarily have the source code at hand.

Comments should be used to give overviews of code and provide additional

information that is not readily available in the code itself.

Consider an example below.

if ( grandTotal >= 1000.00)

{

grandTotal = grandTotal * 0.90;

}

Looking at the code in example above one can figure out that a 10% discount is

being given on orders of $1,000 dollars or more. Why is this being done? Is there a

business rule that says that large orders get a discount? Is there a limited-time

special on large orders or is it a permanent program? Was the original programmer

just being generous? I do not know unless it is documented somewhere, either in the

source code itself or in an external document

Comments should contain only information that is relevant to reading and

understanding the program.

Following are recommended commenting techniques:

When modifying code, always keep the commenting around it up to date.

• Comments should consist of complete sentences and follow active language

naming responsibilities (Adds the element instead of The element is added).

• At the beginning of every routine, XML documentation is used to indicate the

routine's purpose, assumptions, and limitations. A boilerplate comment should be a

brief introduction to understand why the routine exists and what it can do.

Avoid adding comments at the end of a line of code; end-line comments make

code more difficult to read. However, end-line comments are appropriate when

annotating variable declarations. In this case, align all end-line comments at a

common tab stop.

Comment anything that is not readily obvious in the code. This point leads to

allot of subjective interpretations. Use your best judgment to determine an

appropriate level of what it means for code to be not really obvious.

Throughout the application, construct comments using a uniform style, with

consistent punctuation and structure.

3.4.1 Implementation Comments

Block Comments

Page 17: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 17

Block comments are used to provide descriptions of files, methods, data

structures and algorithms. Block comments may be used at the beginning of each

file. They can also be used in other places, such as within methods. Block

comments inside a function or method should be indented to the same level as

the code they describe.

A blank line to set it apart from the rest of the code should precede a block

comment.

// Here is a block comment

// that breaks across multiple

// lines.

Single-Line Comments

Short comments can appear on a single line indented to the level of the code that

follows. If a comment can't be written in a single line, it should follow the block

comment format. A single-line comment should be preceded by a blank line.

Here's an example of a single-line comment in code. if (condition)

{

// Handle the condition.

...

}

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 chunk of code, they should all be indented to

the same tab setting.

Here's an example of a trailing comment in C# code: ss = s1 + s2 + s3; //add the three scores into the sum

a = float(ss) / x; //calculate the mean of the scores

Code-Disabling Comments

The // comment delimiter can comment out a complete line or only a partial line.

Code-disabling comment delimiters are found in the first position of a line of code

flush with the left margin. Visual Studio .NET provides for bulk commenting by

selecting the lines of code to disable and pressing CTRL+K, CTRL+C. To

uncomment, use the CTRL+K, CTRL+U chord.

We should try not to check in the commented code as that may confuse other

developers working on the same code.(Unless there is very specific reason. Code

Reviewer should check this.)

The following is an example of code-disabling comments: if (foo > 1)

{

// Do a double-flip.

...

}

else

{

return false; // Explain why here.

}

// if (bar > 1)

Page 18: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 18

// {

//

// // Do a triple-flip.

// ...

// }

// else

// {

// return false;

// }

3.4.2 Documentation Comments

C# provides a mechanism for developers to document their code using XML. XML

documentation starts with ///.

Consider following points while writing XML documentation…

The documentation must be well-formed XML. If the XML is not well-formed, a

warning is generated and the documentation file will contain a comment

saying that an error was encountered.

Developers are not free to create their own set of tags.

There is a recommended set of tags.

Some of the recommended tags have special meanings:

o The <param> tag is used to describe parameters. If used, the

compiler will verify that the parameter exists and that all parameters

are described in the documentation. If the verification failed, the

compiler issues a warning.

o The cref attribute can be attached to any tag to provide a reference to

a code element. The compiler will verify that this code element exists.

If the verification failed, the compiler issues a warning. The compiler

also respects any using statements when looking for a type described

in the cref attribute.

o The <summary> tag is used by IntelliSense inside Visual Studio to

display additional information about a type or member.

If you need to give information about a class, interface, variable, or method that isn't

appropriate for documentation, use an implementation block comment or single-line

comment immediately after the declaration.

Document comments must not be positioned inside a method or constructor

definition block, because C# associates documentation comments with the first

declaration after the comment.

3.4.3 Comment Tokens

When you add comments with comment tokens to your code, you automatically add

shortcuts to the Task List window. Double-click any comment displayed in the Task

List to move the insertion point directly to the line of code where the comment

begins.

Note: Comments in HTML, .CSS, and .XML markup are not displayed in the Task

List.

Page 19: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 19

To add a comment hyperlink to the Task List window, enter the comment marker.

Enter TODO, HACK, or UNDONE. Add the Comment text.

// ToDo: Fix this later

// Hack: Temporary solution to be enhanced later

3.5 Formatting

Visual studio 2005 has an auto formatting feature and overall we should follow its

style and rules.

3.6 Declaration

3.6.1 Number of Declarations per Line

One declaration per line is recommended since it encourages commenting1. In other

words,

int level;

int size;

Do not put more than one variable or variables of different types on the same line

when declaring them.

3.6.2 Initialization

Try to initialize local variables as soon as they are declared.

string name = myObject.Name;

or

int val = time.Hours;

Note: If you initialize a dialog try to use the using statement:

using (OpenFileDialog openFileDialog = new OpenFileDialog())

{

...

}

3.6.3 Class and Interface Declarations

When coding C# classes and interfaces, the following formatting rules should be

followed:

No space between a method name and the parenthesis "(" starting its

parameter list.

The opening brace "{" appears in the next line after the declaration

statement.

The closing brace " }" starts a line by itself indented to match its

corresponding opening brace.

Page 20: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 20

This is the formatting followed by VS2005 auto formatter.

For example :

class MySample : MyClass, IMyInterface

{

int myInt;

public MySample(int myInt)

{

this.myInt = myInt ;

}

void Inc()

{

++myInt;

}

void EmptyMethod()

{

}

}

3.7 Statements

3.7.1 Simple Statements

Each line should contain only one statement.

3.7.2 Return Statements

A return statement should not use outer most parentheses.

Don't use : return (n * (n + 1) / 2);

use : return n * (n + 1) / 2;

3.7.3 If, if-else, if else-if else Statements

if, if-else and if else-if else statements should look like this:

if (condition)

{

DoSomething();

...

}

if (condition)

Page 21: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 21

{

DoSomething();

...

}

else

{

DoSomethingOther();

...

}

if (condition)

{

DoSomething();

...

}

else if (condition)

{

DoSomethingOther();

...

}

else

{

DoSomethingOtherAgain();

...

}

Note: Always use brackets even if there is only one statement in the loop.

E.g. if(connection!=null)

{

Connection.close();

}

3.7.4 For / Foreach Statements

A for statement should have following form:

for (int i = 0; i < 5; ++i)

{

...

}

Page 22: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 22

A foreach should look like :

foreach (int i in IntList)

{

...

}

3.7.5 While/do-while Statements

A while statement should be written as follows:

while (condition)

{

...

}

An empty while should have the following form:

while (condition) ;

A do-while statement should have the following form:

do

{

...

} while (condition);

3.7.6 Switch Statements

Always use default case with switch statement. A switch statement should be of

following form

switch (condition)

{

case A:

...

break;

case B:

...

break;

default:

...

break;

Page 23: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 23

}

3.7.7 Try-catch Statements

A try-catch statement should follow this form:

try

{

...

}

catch (Exception e)

{

}

or

try

{

...

}

catch (Exception e)

{

...

}

finally

{

...

}

4 Best Practices

This section discuss about the best practices that should be followed while writing

code in c#. The section is divided in subsection based on Performance, Usage,

Design, Globalization, Security, Interoperability and Exceptions.

Most of the content of this section has been taken as it is from

http://www.codeproject.com and FxCop (http://www.gotdotnet.com/team/fxcop/)

rules.

Page 24: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 24

4.1 Performance Prefer the Length property when checking string size

String comparison involves unnecessary overhead. If all you need is to check

whether the string is empty, use the Length property.

Code snippets:

//NO

if ( str != “”)//comparison of two strings

{

...

}

//YES

if ( str.Length > 0)

{

...

}

Prefer StringBuilder instead of string concatenation.

C# string is immutable, i.e., cannot be altered. When you alter a string, you

are actually creating a new string causing the following:

The code uses more memory than necessary.

Creates more work for the garbage collector.

Makes the code execution run slower.

Therefore, you should prefer using StringBuilder (Append method).

Code snippets:

//NO

string strConcat;

ArrayList arrayOfStrings = new ArrayList();

arrayOfStrings.Add("a");

arrayOfStrings.Add("b");

foreach (string s in stringContainer) {

strConcat += s;

}

//YES

StringBuilder sbConcat = new StringBuilder ();

foreach (string s in arrayOfStrings ) {

sbConcat.append(s);

}

For very simple concatenation we should directly add them as

follows:

//Yes

return a + b + c;

//NO

StringBuilder a = new StringBuilder();

Page 25: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 25

a.Append(b);

a.Append(c);

return a;

Avoid unsealed attributes.

The .NET Framework class library provides methods for retrieving custom

attributes. By default, these methods search the attribute inheritance

hierarchy; for example System.Attribute.GetCustomAttribute searches for the

specified attribute type, or any attribute type that extends the specified

attribute type. Sealing the attribute eliminates the search through the

inheritance hierarchy, and can improve performance.

Example: using System;

namespace PerformanceLibrary

{

//AvoidUnsealedAttributes.

[AttributeUsage(AttributeTargets.Class|AttributeTargets.Struct)]

public sealed class DeveloperAttribute: Attribute

{

private string nameValue;

public DeveloperAttribute(string name)

{

nameValue = name;

}

public string Name

{

get

{

return nameValue;

}

}

}

}

Avoid Boxing and UnBoxing as much as possible.

Boxing a value of a value-type consists of two operations:

1. Allocating an object instance.

2. Copying the value-type value into that instance.

Given the above, you should avoid Boxing as much as you can. If you intend to

work with ArrayList, for example, do not declare your data type as struct (Value

type) because ArrayList works with Object (Reference type) and every time you

add an instance of the struct or run over the container, in a loop, a Boxing

process will occur.

The following happens when you copy one of the collection items value into the

struct:

Page 26: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 26

Casting.

Copy the value.

Note: Collections expect object type.

Code snippets:

//NO

struct st { public Int i; }

Arraylist arr = new ArrayList();

for (int i=0 ; i< count; i++)

{

st s;

s.i = 4;

arr.item.add(st) ; //<- Boxing (Allocating an object instance

// + copying the value-type value into that instance)

}

st obj = (st ) arr[0]; //<- Unboxing (casting and copy)

//YES

//Decalre the data type as class.

Class st

{

public int i;

}

Prefer String.Equal method instead of == operator.

Using the string.Equals method is much faster when the strings are matched. So

if you are very keen and need special type of performance and expect that most

of the strings will be the same, use the Equal method.

Note: The differences in performance are negligible and effect only numerous

operations.

Code snippets:

string s1= "code";

string s2 = "code1";

//No:

if(s1 == s2)

{

...

}

//Yes:

if(s1.Equals(s2))

{

...

}

Use Native Image Generator (nGen.exe) in case of long and heavy

initialization.

Page 27: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 27

The .NET Framework runs C# assemblies using the JIT compiler. Each code that

is executed for the first time is being compiled. In case of heavy and long initialization in your assembly, you might want to use the nGen .NET tool.

"The nGen creates a native image from a managed assembly and installs it into the native image cache on the local computer.

Once you create a native image for an assembly, the runtime automatically uses

that native image each time it runs the assembly. You do not have to perform

any additional procedures to cause the runtime to use a native image. Running

Ngen.exe on an assembly allows the assembly to load and execute faster,

because it restores code and data structures from the native image cache rather than generating them dynamically." (MSDN 2005)

You do not have to lose the advantage of JIT compilation, because you can call

the nGen command on the installation machine through your project setup, using:

ngen [options] [assemblyName |assemblyPath ]

Prefer 'for' over 'foreach'.

'foreach' and 'for' statements serve the same goal - run in loop over block of statements.

The main differences in using the foreach statement are that you do not need to

deal with increments and with the end of the loop expression. Moreover, the

foreach statement is designed to traverse through the entire collection. One can say that foreach is a private case of for.

In the code snippets below, we can see that both loop blocks produce the same

results, only under the hood the foreach hurts the performance. More variables

are involved and additional heavy array copy.

The foreach is far handier to use especially for collections but if your code runs

over large collections, prefer using 'for'.

Code snippets:

//foreach

int[] arrayOfInts= new int[5];

int sum= 0;

foreach(int i arrayOfInts) {

sum+= i;

}

//for

int[] arrayOfInts= new int[1];

int sum= 0;

for(int i = 0; i < arrayOfInts.Length; i++) {

sum+= arrayOfInts[i];

Page 28: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 28

}

Do not cast unnecessarily.

Duplicate casts degrade performance, especially when the casts are

performed in compact iteration statements. For explicit duplicate cast

operations, store the result of the cast in a local variable and use the local

variable instead of the duplicate cast operations.

If the C# is operator is used to test whether the cast will succeed before the

actual cast is performed, consider testing the result of the as operator

instead. This provides the same functionality without the implicit cast

operation performed by the is operator.

Example: namespace PerformanceLibrary

{

public sealed class SomeClass

{

private SomeClass() {}

// NO.

public static void UnderPerforming(ArrayList list)

{

foreach(object obj in list)

{

// The 'is' statement performs a cast operation.

if(obj is Control)

{

// The 'as' statement performs a duplicate cast

operation.

Control aControl = obj as Control;

// Use aControl.

}

}

}

// Yes.

public static void BetterPerforming(ArrayList list)

{

foreach(object obj in list)

{

Control aControl = obj as Control;

if(aControl != null)

{

// Use aControl.

}

}

}

}

}

4.2 Usage

Use string.Empty instead of “”

Page 29: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 29

//Avoid

string name = “”;

//Correct

string name = string.Empty;

Use the 'checked' keyword to avoid overflow.

Code snippets:

//NO

short shortNum;

int i = 32768;

shortNum = (short) i;

// problem after statment excution

// the shortNum variable has an uninitialized value,

//YES

try {

shortNum = checked((short)i); // solution

}

catch(OverflowException efx) {}

Use Explicit interface to 'hide' the implementation of an interface

Implementing an interface explicitly 'hides' the interface methods. Visual Studio

does not display the interface methods in the intellisense.

Code snippets:

//interface definition

public interface IChild{

bool IsHuman();

void lie();

}

//class definition

public Pinocchio: IChild {

IChild.IsHuman() //explicit interface implementation

{

}

public void Lie(); //regular interface implementation

}

//using the object

static void main()

{

// Visual studio will not display

// the isHuman mwthod in the intellisence.

Pinocchio o = new Pinocchio();

((IChild) o).IsHuman(); // using the IsHuman method explicitly.

o.Lie();

}

Collection properties should be read only.

Page 30: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 30

A writable collection property allows a user to replace the collection with an

entirely different collection. A read-only property stops the collection from

being replaced while still allowing the individual members to be set. If

replacing the collection is a goal, the preferred design pattern is to include a

method to remove all the elements from the collection and a method to re-

populate the collection.

Example: The following example shows a type with a writable collection

property and shows how the collection can be replaced directly. In addition,

the preferred manner of replacing a read-only collection property using Clear

and AddRange methods is shown.

namespace UsageLibrary

{

public class WritableCollection

{

ArrayList strings;

public ArrayList SomeStrings

{

get { return strings; }

// Violates the rule.

set { strings = value; }

}

public WritableCollection()

{

strings = new ArrayList(

new string[] {"IEnumerable", "ICollection", "IList"}

);

}

}

class ReplaceWritableCollection

{

static void Main()

{

ArrayList newCollection = new ArrayList(

new string[] {"a", "new", "collection"} );

// strings is directly replaced with newCollection.

WritableCollection collection = new

WritableCollection();

collection.SomeStrings = newCollection;

// newCollection is added to the cleared strings

collection.

collection.SomeStrings.Clear();

collection.SomeStrings.AddRange(newCollection);

}

}

}

Page 31: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 31

Use @ to ease the work with literal paths.

Code snippets:

//Old way

string sFilePath = “c:\\a\\b\\c.txt”;

//The C# way

string sFilePath = @”c:\a\b\c.txt”;

Make your API assembly CLS Compliant.

The CLS-Compliant attribute cause the compiler to check whether your public

exposed types in the assembly are CLS-Compliant.

Prefer to define the attribute for the entire assembly, especially for API. The

incentive to create a CLS compliant assembly is that any assembly written in one

of the .NET aware languages can use your assembly more efficiently because

there is no data type interoperability.

Code snippets:

using System;

[assembly:CLSCompliant(true)]

Define destructor and implement IDisposable interface for classes

that use native resource directly.

You should define a destructor whenever you use native code in your assembly,

i.e., use types that are not managed by the garbage collector. The compiler

changes the destructor method to Finalize method (can be seen in the MSIL using

the ILDasm.exe).

The Garbage collector marks a class with destructor as Finalized and calls the

Finalize method while destructing the object. This behavior guarantees that your

release of resources in the destructor will occur.

But, what if you want to release the resources immediately? For this purpose,

you should implement the IDisposable interface and call the Dispose method

when you want to release the object.

Note 1: Do not use destructor if your class does not use native / unmanaged

resources. If you do so, you create unnecessary work for the garbage collector.

Note 2: If you implement the IDisposable and a destructor, you should call the

Dispose method from the destructor to force the object to release resources

immediately.

Code snippets:

~my class {

if ( true == b)

{

}

}

//The MSIL code:

protected override void Finalize()

{

try {

Page 32: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 32

if ( true == b)

{

}

}

finally { base.Finalize();}

}

Avoid the use of GC.Collect.

The GC.Collect method forces garbage collection of all generations.

The performance is hurt during the call to GC.Collect, the application execution is

paused. Moreover, the method might cause the promotion of short lived objects

to a higher generation, i.e., those object live longer than it should in the first

place.

If you must use it in order to reclaim the maximum amount of available memory,

use the method only on generation 0.

Code snippets:

//No:

GO.Collect();

//Yes:

GC.Collect(0);

4.3 Design Abstract type should not have public constructors

Constructors on abstract types can only be called by derived types. Because

public constructors create instances of a type, and you cannot create instances of

an abstract type, an abstract type with a public constructor is incorrectly

designed.

Example: namespace DesignLibrary

{

public abstract class BadAbstractClassWithConstructor

{

//WRONG: AbstractTypesShouldNotHaveConstructors.

public BadAbstractClassWithConstructor()

{

// Add constructor logic here.

}

}

public abstract class GoodAbstractClassWithConstructor

{

protected GoodAbstractClassWithConstructor()

{

// Add constructor logic here.

}

}

}

Consider passing base types as parameters.

When a base type is specified as a parameter in a method declaration, any type

derived from the base type can be passed as the corresponding argument to the

Page 33: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 33

method. When the argument is used inside the method body, the specific method

that is executed depends on the type of the argument. If the additional

functionality provided by the derived type is not required, use of the base type

allows the method to be more widely utilized.

Example: namespace DesignLibrary

{

public class StreamUser

{

int anInteger;

public void ManipulateFileStream(FileStream stream)

{

while((anInteger = stream.ReadByte()) != -1)

{

// Do something.

}

}

public void ManipulateAnyStream(Stream anyStream)

{

while((anInteger = anyStream.ReadByte()) != -1)

{

// Do something.

}

}

}

class TestStreams

{

static void Main()

{

StreamUser someStreamUser = new StreamUser();

MemoryStream testMemoryStream = new MemoryStream(new byte[]

{});

using(FileStream testFileStream =

new FileStream("test.dat", FileMode.OpenOrCreate))

{

// Cannot be used with testMemoryStream.

someStreamUser.ManipulateFileStream(testFileStream);

someStreamUser.ManipulateAnyStream(testFileStream);

someStreamUser.ManipulateAnyStream(testMemoryStream);

}

}

}

}

Enums should have zero value

The default value of an un-initialized enumeration, like other value types, is zero.

A non-flags attributed enumeration should define a member with the value of

zero so that the default value is a valid value of the enumeration. If appropriate,

name the member 'None'. Otherwise, assign zero to the most commonly used

member. Note that if the value of the first enumeration member is not set in the

declaration, its value is zero by default.

Page 34: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 34

If an enumeration that has the FlagsAttribute applied defines a zero-valued

member, its name should be 'None' to indicate that no values have been set in

the enumeration. Using a zero-valued member for any other purpose is contrary

to the use of the FlagsAttribute in that the AND and OR bitwise operators are

useless with the member. This implies that only one member should be assigned

the value zero. Note that if there are multiple members with the value zero in a

flags-attributed enumeration, Enum.ToString() returns incorrect results for

members that are not zero.

Example:

public enum TraceLevel

{

Off = 0,

Error = 1,

Warning = 2,

Info = 3,

Verbose = 4

}

//Correct

[Flags]

public enum TraceOptions

{

None = 0,

CallStack = 0x01,

LogicalStack = 0x02,

DateTime = 0x04,

Timestamp = 0x08,

}

//Wrong

[Flags]

public enum BadTraceOptions

{

CallStack = 0,

LogicalStack = 0x01,

DateTime = 0x02,

Timestamp = 0x04,

}

Mark assemblies with ComVisible.

Page 35: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 35

The ComVisibleAttribute attribute determines how COM clients access

managed code. Good design dictates that assemblies explicitly indicate COM

visibility. COM visibility can be set for an entire assembly and then overridden

for individual types and type members. If the attribute is not present, the

contents of the assembly are visible to COM clients.

[assembly: ComVisible(false)] //can be true or false

Properties should not be write only.

Get accessors provide read access to a property and set accessors provide

write access. While it is acceptable and often necessary to have a read-only

property, the design guidelines prohibit the use of write-only properties

because allowing a user to set a value, and then preventing the user from

viewing the value does not provide any security. Also, without read access,

the state of shared objects cannot be viewed, which limits their usefulness.

Example: public class BadClassWithWriteOnlyProperty

{

string someName;

// Violates rule PropertiesShouldNotBeWriteOnly.

public string Name

{

set

{

someName = value;

}

}

}

public class GoodClassWithReadWriteProperty

{

string someName;

public string Name

{

get

{

return someName;

}

set

{

someName = value;

}

}

}

Do not use string as type for URI parameters/properties or URI

return values.

A string representation of a URI is prone to parsing and encoding errors,

and can lead to security vulnerabilities. If a method takes a string

representation of a URI, a corresponding overload should be provided that

Page 36: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 36

takes an instance of the Uri class, which provides these services in a safe

and secure manner.

Example:

namespace DesignLibrary

{

public class ErrorProne

{

string someUri;

// Violates rule UriPropertiesShouldNotBeStrings.

public string SomeUri

{

get { return someUri; }

set { someUri = value; }

}

// Violates rule UriParametersShouldNotBeStrings.

public void AddToHistory(string uriString) { }

// Violates rule UriReturnValuesShouldNotBeStrings.

public string GetRefererUri(string httpHeader)

{

return "http://www.adventure-works.com";

}

}

public class SaferWay

{

Uri someUri;

// To retrieve a string, call SomeUri.ToString().

// To set using a string, call SomeUri = new

Uri(string).

public Uri SomeUri

{

get { return someUri; }

set { someUri = value; }

Page 37: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 37

}

public void AddToHistory(string uriString)

{

// Check for UriFormatException.

AddToHistory(new Uri(uriString));

}

public void AddToHistory(Uri uriType) { }

public Uri GetRefererUri(string httpHeader)

{

return new Uri("http://www.adventure-works.com");

}

}

}

4.4 Globalization Do not hardcode locale specific strings.

Example: namespace GlobalizationLibrary

{

class WriteSpecialFolders

{

static void Main()

{

string string0 = "C:";

// Do Not.

string string1 = @"\Documents and Settings";

string string2 = @"\All Users";

string string3 = @"\Application Data";

Console.WriteLine(string0 + string1 + string2 +

string3);

// Do use

Console.WriteLine(Environment.GetFolderPath(

Environment.SpecialFolder.CommonApplicationData));

}

}

}

Do pass IFormat provider and CultureInfo.

Page 38: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 38

When a CultureInfo or System.IFormatProvider object is not supplied,

the default value supplied by the overloaded member might not have the

effect that you want in all locales. Also, .NET Framework members choose

default culture and formatting based on assumptions that might not be

correct for your code. To ensure the code works as expected for your

scenarios, you should supply culture-specific information

Example:

namespace GlobalLibGlobalLibrary

{

public class IFormatProviderTest

{

public static void Main()

{

string dt = "6/4/1900 12:15:12";

// The default behavior of DateTime.Parse is to use

// the current culture.

// Here IFormatProvider has not been specified.

DateTime myDateTime = DateTime.Parse(dt);

Console.WriteLine(myDateTime);

//This gives out put as 6/4/1900 12:15:12 PM

// Change the current culture to the required culture (e.g

French),

// and parsing the same string yields a different value.

Thread.CurrentThread.CurrentCulture = new

CultureInfo("Fr-fr", true);

myDateTime = DateTime.Parse(dt);

Console.WriteLine(myDateTime);

//This gives out put as 06/04/1900 12:15:12

}

}

}

4.5 Security

Array fields should not be read only

When you apply the readonly modifier to a field that contains an array, the

field cannot be changed to refer to a different array; however, the elements of

the array stored in a read-only field can be changed. Code that makes

decisions or performs operations based on the elements of a publicly accessible

read-only array might contain an exploitable security vulnerability.

Example: public class MyClassWithReadOnlyArrayField

{

Page 39: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 39

// The field grades is public, and therefore vulnerable to any caller.

public readonly int[] grades = {90, 90, 90};

// The field privateGrades is private, but is still vulnerable because it is returned to callers by the GetPrivateGrades method.

private readonly int[] privateGrades = {90, 90, 90};

private readonly int[] securePrivateGrades = {90, 90, 90};

// Making the array private does not protect it because it is

passed to others.

public int[] GetPrivateGrades()

{

return privateGrades;

}

}

Asserts require security demands

Asserting security permission without performing any security checks can

leave an exploitable security weakness in your code

SecurityPermission securePermission

= new SecurityPermission(PermissionState.Unrestricted);

/*Demand some permission(s) that all callers must have before

you will assert permission on their behalf.

In this example, all callers are required to have all security

permissions before permission to access environment variables is

asserted.

*/

securePermission.Demand();

//If the demand fails, a SecurityException is thrown.

Public types that implement non-public interfaces should be sealed

Interface methods have public accessibility, which cannot be changed by the

implementing type. An internal interface creates a contract that is not intended

to be implemented outside the assembly that defines the interface. A public

type that implements a method of an internal interface using the virtual

modifier allows the method to be overridden by a derived type that is outside

the assembly. If a second type in the defining assembly calls the method and

expects an internal-only contract, behavior might be compromised when,

instead, the overridden method in the outside assembly is executed. This

creates security vulnerability. // Internal by default.

interface IValidate

{

bool UserIsValidated();

}

Page 40: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 40

public class BaseImplementation : IValidate

{

public virtual bool UserIsValidated()

{

return false;

}

}

public class UseBaseImplementation

{

public void SecurityDecision(BaseImplementation

someImplementation)

{

if(someImplementation.UserIsValidated() == true)

{

Console.WriteLine("Account number & balance.");

}

else

{

Console.WriteLine("Please login.");

}

}

}

Virtual methods and their Overrides require the same Link Demand

status.

If a virtual method has a Link Demand, so should any override of it, and if an

Override has a Link Demand, so should the overridden virtual method

Ex: If a method in the base class is declared as virtual, and has the security

status, then immediate overriding of that member should also have the same

security status.

Example: public interface ITestOverrides

{

[EnvironmentPermissionAttribute(SecurityAction.LinkDemand,

Unrestricted=true)]

Object GetFormat(Type formatType);

}

public class OverridesAndSecurity : ITestOverrides

{

// Rule violation: The interface has security, and this

implementation does not.

object ITestOverrides.GetFormat(Type formatType)

{

return (formatType == typeof(OverridesAndSecurity) ?

this : null);

}

// These two methods are overridden by DerivedClass and

DoublyDerivedClass.

[EnvironmentPermissionAttribute(SecurityAction.LinkDemand,

Unrestricted=true)]

public virtual void DoSomething()

Page 41: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 41

{

Console.WriteLine("Doing something.");

}

public virtual void DoSomethingElse()

{

Console.WriteLine("Doing some other thing.");

}

}

public class DerivedClass : OverridesAndSecurity,

ITestOverrides

{

// Rule violation: The interface has security, and this

implementation does not.

public object GetFormat(Type formatType)

{

return (formatType == typeof(OverridesAndSecurity) ?

this : null);

}

// Rule violation: This does not have security, but the

base class version does.

public override void DoSomething()

{

Console.WriteLine("Doing some derived thing.");

}

// Rule violation: This has security, but the base class

version does not.

[EnvironmentPermissionAttribute(SecurityAction.LinkDemand,

Unrestricted=true)]

public override void DoSomethingElse()

{

Console.WriteLine("Doing some other derived thing.");

}

}

public class DoublyDerivedClass : DerivedClass

{

// The OverridesAndSecurity version of this method does not

have security.

// Base class DerivedClass's version does.

// The DoublyDerivedClass version does not violate the

rule, but the

// DerivedClass version does violate the rule.

public override void DoSomethingElse()

{

Console.WriteLine("Doing some other derived thing.");

}

}

Static constructors should be private

A static constructor, also called a class constructor, is used to initialize a type.

The system calls the static constructor before the first instance of the type is

Page 42: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 42

created or any static members are referenced. The user has no control over

when the static constructor is called. If a static constructor is not private, it

can be called by code other than the system. Depending on the operations

performed in the constructor, this can cause unexpected behavior.

4.6 Interoperability Do not use AutoDual ClassInterfaceType

Types that use a dual interface allow clients to bind to a specific interface

layout. Any changes in a future version to the layout of the type or any base

types will break COM clients that bind to the interface. By default, if the

ClassInterfaceAttribute attribute is not specified, a dispatch-only interface

is used.

Example: // This violates the rule.

[ClassInterface(ClassInterfaceType.AutoDual)]

public class DualInterface

{

public void SomeMethod() {}

}

public interface IExplicitInterface

{

void SomeMethod();

}

[ClassInterface(ClassInterfaceType.None)]

public class ExplicitInterface : IExplicitInterface

{

public void SomeMethod() {}

}

Use StructLayout attribute for classes and structs when using COM

Interop.

The attributes cause the compiler to pack the structure in sequential memory

so that it can be sent to unmanaged code correctly (unmanaged code that

expects a specific layout).

Code snippets:

using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential)]

public struct st

{

int i;

float f;

}

Auto layout types should not be ComVisible

Auto layout types are managed by the common language runtime. The layout

of these types can change between versions of the .NET Framework, which

will break COM clients that expect a specific layout. Note that if the

Page 43: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 43

StructLayoutAttribute attribute is not specified, the C#, Visual Basic, and

C++ compilers specify the Sequential layout for value types

Example: // This violates the rule.

[StructLayout(LayoutKind.Auto)]

[ComVisible(true)]

public struct AutoLayout

{

public int ValueOne;

public int ValueTwo;

}

// This satisfies the rule.

[StructLayout(LayoutKind.Explicit)]

[ComVisible(true)]

public struct ExplicitLayout

{

[FieldOffset(0)]

public int ValueOne;

[FieldOffset(4)]

public int ValueTwo;

}

Avoid overloads in ComVisible interfaces

When overloaded methods are exposed to COM clients, only the first method

overload retains its name. Subsequent overloads are uniquely renamed by

appending to the name an underscore character '_' and an integer that

corresponds to the order of declaration of the overload. For example, consider

the following methods: void SomeMethod(int valueOne);

void SomeMethod(int valueOne, int valueTwo, int valueThree);

void SomeMethod(int valueOne, int valueTwo);

These methods are exposed to COM clients as:

void SomeMethod(int valueOne);

void SomeMethod_2(int valueOne, int valueTwo, int valueThree);

void SomeMethod_3(int valueOne, int valueTwo);

Example: // This interface violates the rule.

[ComVisible(true)]

public interface IOverloadedInterface

{

void SomeMethod(int valueOne);

void SomeMethod(int valueOne, int valueTwo);

}

// This interface satisfies the rule.

[ComVisible(true)]

public interface INotOverloadedInterface

{

void SomeMethod(int valueOne);

Page 44: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 44

void AnotherMethod(int valueOne, int valueTwo);

}

4.7 Exceptions

A well-designed set of error handling code blocks can make a program more robust

and less prone to crashing because the application handles such errors. The following

list contains suggestions on best practices for handling exceptions:

Know when to set up a try/catch block. For example, you can

programmatically check for a condition that is likely to occur without using

exception handling. In other situations, using exception handling to catch an

error condition is appropriate.

The method you choose depends on how often you expect the event to occur.

If the event is truly exceptional and is an error (such as an unexpected end-

of-file), using exception handling is better because less code is executed in

the normal case. If the event happens routinely, using the programmatic

method to check for errors is better. In this case, if an exception occurs, the

exception will take longer to handle.

Use try/finally blocks around code that can potentially generate an exception

and centralize your catch statements in one location. In this way, the try

statement generates the exception, the finally statement closes or deallocates

resources, and the catch statement handles the exception from a central

location.

Always order exceptions in catch blocks from the most specific to the least

specific. This technique handles the specific exception before it is passed to a

more general catch block.

End exception class names with the word "Exception.".

When creating user-defined exceptions, you must ensure that the metadata

for the exceptions is available to code executing remotely, including when

exceptions occur across application domains. For example, suppose

Application Domain A creates Application Domain B, which executes code that

throws an exception. For Application Domain A to properly catch and handle

the exception, it must be able to find the assembly containing the exception

thrown by Application Domain B. If Application Domain B throws an exception

that is contained in an assembly under its application base, but not under

Application Domain A's application base, Application Domain A will not be able

to find the exception and the common language runtime will throw a

FileNotFoundException. To avoid this situation, you can deploy the assembly

containing the exception information in two ways:

o Put the assembly into a common application base shared by both

application domains, or

o If the domains do not share a common application base, sign the

assembly containing the exception information with a strong name and

deploy the assembly into the global assembly cache.

In C#, use at least the three common constructors when creating your own

exception classes.

Page 45: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 45

using System;

public class ListNotFoundException: ApplicationException

{

public ListNotFoundException()

{

}

public ListNotFoundException(string message) : base(message)

{

}

public ListNotFoundException(string message, Exception inner)

: base(message, inner)

{

}

}

In most cases, use the predefined exceptions types. Define new exception

types only for programmatic scenarios. Introduce a new exception class to

enable a programmer to take a different action in code based on the

exception class.

Do not derive user-defined exceptions from the Exception base class. For

most applications, derive custom exceptions from the Application Exception

class.

Instead of sending error messages directly to the user, in case error occurs ,

the exception code should be returned and then based on user‟s preferred

language appropriate messages should be shown to the user.

Use grammatically correct error messages, including ending punctuation.

Each sentence in a description string of an exception should end in a period.

Provide Exception properties for programmatic access. Include extra

information in an exception (in addition to the description string) only when

there is a programmatic scenario where the additional information is useful.

Return null for extremely common error cases. For example, File.Open

returns null if the file is not found, but throws an exception if the file is

locked.

Design classes so that an exception is never thrown in normal use. For

example, a FileStream class exposes another way of determining whether the

end of the file has been reached. This avoids the exception that is thrown if

you read past the end of the file.

Throw an InvalidOperationException if a property set or method call is not

appropriate given the object's current state.

Throw an ArgumentException or a class derived from ArgumentException if

bad parameters are passed.

Page 46: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 46

The stack trace begins at the statement where the exception is thrown and

ends at the catch statement that catches the exception. Be aware of this fact

when deciding where to place a throw statement.

Use exception builder methods. It is common for a class to throw the same

exception from different places in its implementation. To avoid excessive

code, use helper methods that create the exception and return it.

Alternatively, use the exception's constructor to build the exception. This is

more appropriate for global exception classes, such as ArgumentException.

Throw exceptions instead of returning an error code or HRESULT.

Clean up intermediate results when throwing an exception. Callers should be

able assume that there are no side effects when an exception is thrown from

a method.

Additional information about throwing exceptions:

There is a basic difference between two kinds of exception thrown. So here it

should not only be 'where' but 'what' also.

For more information please see

http://msdn.microsoft.com/library/default.asp?url=/library/en-

us/cpguide/html/cpconbestpracticesforhandlingexceptions.asp

The statement

throw e;

This will reset the stack trace in exception object "e" so that the stack trace

begins on the same line as the throw statement. The statement:

throw;

This will re-throw the original exception object without resetting the stack

trace. So if you catch an exception, examine and decide you don't really want to

handle it and have nothing of value to add, then simply use

throw;

If you want to erase from the stack trace the original line that generated the

exception (in essence, hide information) then use:

throw e;

If you want to add context (this is usually most people do), then use something

like this:

throw new Exception("Message",ex);

This preserves the original exception as the inner exception in the exception

object.

5 Project Settings and Structure

Always build your project with warning level 4.

Page 47: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 47

Always explicitly state your supported runtime version in the application

configuration file <? xml version="1.0" ?>

<configuration>

<startup>

<supportedRuntime version="1.1.5000.0" />

<supportedRuntime version="2.0.5500.0" />

</startup>

</configuration>

Populate all fields in AssemblyInfo.cs such as company name, description and

copyright notice. For more information please see any automatically created

Assemblyinfo.cs file. Following values must be used for the attribute given

below…

[assembly: AssemblyCompany("Company Inc.")]

[assembly: AssemblyCopyright("Copyright (c) "+ Year + " Company

, Inc.")]

[assembly: AssemblyTrademark("Company")]

[assembly: AssemblyCulture("")]

[assembly:CLSCompliant(true)]

Page 48: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 48

Put copyright notice also on the top of every cs file. Following copyright

information should be used.

#region Copyright (c) 2005-2006 Company , Inc. All rights

reserved

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

// Copyright (c) 2005 Company.

//

//The copyright to the computer software herein is proprietary

//and remains the property of Company. It may //be used and/or

copied only with the written consent of Company // or in

accordance with the terms and conditions //stipulated in the

agreement/contract under which this software //has been supplied.

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

#endregion

Note: You can modify templates in the Visual studio so that each time you add a

new file the copyright notice is automatically added to the created file.

E.g. To add copyright notice when a new class is created change the following

template(For VS .NET 2003)

<VS Installation Directory>\Microsoft Visual Studio .NET

2003\VC#\VC#Wizards\CSharpAddClassWiz\Templates\1033\ NewCSharpFile.cs

All assembly references in the same solution should use relative path. (This is

by default in Visual Studio)

Always sign your assemblies, including client applications. For more

information regarding signing assemblies please see any automatically

created Assemblyinfo.cs file.

Make sure there are no cyclic references among assemblies.

6 References:

http://msdn2.microsoft.com/en-us/library/ms229042(en-US,VS.80).aspx

http://www.gotdotnet.com/Team/FxCop/docs/rules/NamingRules.aspx

http://www.csharpfriends.com/Articles/getArticle.aspx?articleID=336

http://www.tech.purdue.edu/Cpt/Courses/cpt355/C_Sharp_Coding_Standards

_and_Guidelines.htm

http://www.icsharpcode.net/TechNotes/SharpDevelopCodingStyle03.pdf

Page 49: C# Coding Guidelines and Best Practices€¦ · Dot Net Development Open Book C# Coding Guidelines and Best Practices Pradeep Kumar Mishra . C# Coding Guidelines and Best Practices

C# Coding Guidelines and Best Practices

Pradeep Kumar Mishra Page 49

Appnedix A

Hungarian notation: It describes the practice of prefixing variable names with a

tag that indicates what kind of object or data they hold. Contrary to popular belief,

this does not mean that the prefix should indicate the data type of the variable, but,

rather, it should give someone reviewing the code a clue as to what the variable

contains and what it is intended to be used for. Prefixing a variable with a tag

indicating its data type is better known as System notation, and should not be used.

Example of Hungarian notation for variables:

int rowCount = 0;

int colCount = 0;

Notice that both variables have integer data types, and both are intended to hold a

count of something, but it is very clear that rowCount is a count of a rows, and

colCount is a count of columns.

Anyone reviewing the following code:

rowCount = userData.Columns.Count;

colCount = userData.Rows.Count;

… would be able to spot an error in the usage of the variables.

Hungarian notation, when used properly, gives a readable quality to the code, and

makes code easier to write, debug, and maintain because it helps correct code look

correct, and incorrect code look incorrect.

Hungarian notation is not recommended in c# by Microsoft. Some of the reasons

why not to use Hungarian notations are as follows…

In object-oriented programming, it is rarely necessary as code is modularized

enough so that the declaration is often visible or easily found if there is a

question as to an identifier‟s type.

The VS.NET IDE offers several ways to quickly identify an object‟s type:

o Tooltip; seen by “mousing over” the identifier.

o Intellisense tells you the type.

o Type information is provided in the debugger.

You can often tell an identifier‟s type by the usage. This is particularly true in

OO environments where you often set an identifier to a “new” followed by the

type or when a method tells you what type it returns, such as

GetXmlReader() or LoadControl().