C# Coding Guidelines and Best Programming Practices
Introduction:
Classes - Class names should always be a noun and, again, should be meaningful. Avoid verbs.Every class should have xml comments
Handler:
Use Camel casing for method parameters. Do not abbreviate variable names. Variable names should again be descriptive and meaningful.
//Good:
//Not good:
Variables - Do not abbreviate variable names. Variable names should again be descriptive and meaningful. Scope of variable should be justified, nit should declare very nearest to use.
//Good
//Not Good
Constants: Constants should be declare at top of the class and should be in capital letter.
Private member variables – This section is very confusing as some developer want to use Hungarian notation, but I don’t want to use Hungarian notation to class variables. In earlier days, most programmers liked it: having the data type as a prefix for the variable name and using
Do not make the member variables public or protected. Keep them private and expose public/protectedproperties. Never hardcode a path or drive name in code. Get the application path programmatically and use relative path. Never assume that your code will run from drive C: .You never know; some users may run it from a network or from a Z: .
Custom attributes - Suffix all attribute class names with
Custom exceptions - Suffix all custom exception names with
<>
Control Flow:
To keep you out of trouble, execution statements should always be enclosed within curly braces.
The For Statements:
As for the if statement, execution statements should always be enclosed within curly braces.
The ForEach Statement:
As for the for statement, execution statements should always be enclosed within curly braces.
Note
Using the foreach statement to change a collection may cause unpredictable side effects.
The While Statement:
As for the foreach statement, execution statements should always be enclosed within curly braces.
Note
If the specified expression never evaluates to true, the statement will never be executed.
The Do While Statement:
The Switch Statement:
//Good:
//Not good:
//Good
Miscellaneous Tips
Name methods using verb-object pair
Properly name properties
When you will deploy the application in that time you will comment hardcoded value then some and uncomment second line but some time miss to delete fist line and without curly braces actual IP address function will not executed based on condition, ]so avoid these condition use curly braces.
• Use Pascal casing in resource keys.
• Provide descriptive rather than short identifiers. Keep them concise where possible, but don’t sacrifice readability.
Use Extension method and avoid LINQ for simple expressions
Example:
Prefer using the extension methods from the System.Linq namespace.
Since LINQ queries should be written out over multiple lines for readability, the second example is a bit more readable.
Use Lambda expressions instead of delegates
Return an IEnumerable<T> or ICollection<T> instead of a concrete collection class
ref : http://www.stackdotnet.com/2011/12/c-coding-guidelines-and-best.html
In this post I am trying to explain the best practice coding guidelines.A style guide is a set of mandatory requirements for layout and formatting. Uniform style makes it easier for other developers to grasp the essence of your programs quickly. A style guide makes you more productive because it reduces gratuitous choice. If you don't have to make choices about trivial matters, you can spend your energy on the solution of real problems.
Naming Conventions:
- Pascal casing: The first character is upper case, and the first letter of each word is also upper case. All other characters are lower case; for example, FirstName.
- Camel casing: The first character is not upper case, but the first letter of each word is upper case. All other characters are lower case; for example, firstName.
- All Upper:All the characters are in capitals with an underscore between the two words. Example: FIRST_NAME
Source files should be kept as short as possible. Put every class in a separate file, and name that file like the class followed by the .cs extension. Map namespaces one-to-one to the directory layout. For example, if Thermota.Core is the root namespace, it should be mapped to the Thermota.Core directory, while the nested namespace
Thermota.Core.Tests should be mapped to the Thermota.Core / Thermota.Core.Tests path.
Organize the material in each source file as follows:
1. Appropriate using statements with using Directive region
2. namespace statement, if appropriate
3. A class, struct, or enum
#region using Directives Using System; … … #endregion |
/// <summary> /// Class for measuring the temperature using thermometer. /// </summary> Public class Thermometer { ... } |
Define features in alphabetical order and group them as following:
· const fields
· readonly fields
· static variables
· Instance (or class) variables
· Properties
· Operators
· Operators
· Methods
· Nested classes
· Public features should precede protected and private features.
Leave a blank line after each group of related fields or variables as well as after every property or method. All instance variables must be private. Use properties to provide access to them. (However, instance variables of a private inner class or struct may be public.) Methods, properties, and const fields can be public, protected, or private, as appropriate.
All features must be tagged public, protected, or private. Do not use the default visibility.
Method/Handler:
Every method should be preceded by a XML documentation comment starting with Method/Handler for explaining the purpose of the method, Method name should follow the Pascal casing:
Method:
/// <summary> /// Method for doing something. /// </summary> /// <param name = " name ">Name is string type and input parameter.</param> void SayHello(string name) { ... } |
Handler:
/// <summary> /// Handler for the closing of the role window. /// </summary> /// <param name = "sender">The probe that generated the event. Window in this ///case.</param> /// <param name = "e">The window close event argument generated by the ///window.</param> private void OnRoleClosed(Object sender, WindowClosedEventArgs e) { ... } |
//Good
int ResizeImage(int imageCount) { for( int count=0;count< imageCount;count++) { … } } |
//Not good
int ResizeImage(int i) { for( int j=0;j< i;j++) { … } } |
Avoid having too-large files. If a file has more than 300-400 lines of code, you must consider refactoring the code into helper classes. Avoid writing very long methods. A method should typically have 1-25 lines of code. If a method has more than 25 lines of code, you must consider refactoring it into separate methods. The method's name should tell what it does. Do not use misleading names. If the method name is obvious, there is no need of documentation explaining what the method does.
A method should do only "one job." Do not combine more than one job in a single method, even if those jobs are very small.
//Good:
Void SavePhoneNumber( string phoneNumber) { …. } |
//Not good:
Void Save( string phoneNumber) { …. } |
Variables - Do not abbreviate variable names. Variable names should again be descriptive and meaningful. Scope of variable should be justified, nit should declare very nearest to use.
//Good
int customerCount = 0; string temperature = string.Empty; |
//Not Good
int i=0; private string t = ""; |
Constants: Constants should be declare at top of the class and should be in capital letter.
private const int MAXTEMPERATURE = 100; |
Private member variables – This section is very confusing as some developer want to use Hungarian notation, but I don’t want to use Hungarian notation to class variables. In earlier days, most programmers liked it: having the data type as a prefix for the variable name and using
m_
as the prefix for member variables, also don’t use ‘_’ underscore in class variables.Usage of data type and M_ to represent member variables should not be done. All variables should use Camel casing. Use meaningful, descriptive words to name variables:
- Do not use abbreviations. Use name, address, salary etc. instead of nam, addr, sal.
- Do not use single character variable names like i, n, x, etc. Use names like index and temp.
//Good
<> public class Image { private int initialWidth; private string fileName; ... } |
//Not Good
public class Image { private int m_initialWidth; private string _filename; ... } |
Properties:
Every property should be preceded by a XML documentation start with Gets or Sets and Gets for only read only property and Sets for the write only property, comment explaining the purpose of the property and describing the value it represents:
/// <summary> /// Gets or sets the temperature. /// </summary> public int Temperature { get { return temperature; } set { temperature = value; } |
Do not make the member variables public or protected. Keep them private and expose public/protectedproperties. Never hardcode a path or drive name in code. Get the application path programmatically and use relative path. Never assume that your code will run from drive C: .You never know; some users may run it from a network or from a Z: .
Custom attributes - Suffix all attribute class names with
Attribute
. The C# compiler recognizes this and allows you to omit it when using it.public class IsTestedAttribute : Attribute { public override string ToString() { return "Is Tested"; } } //"Attribute" suffix can be omitted [IsTested] public void Ring(); |
Exception
.<>
public class UserNotExistentException : System.ApplicationException { ... } |
Control Flow:
The If Statement:
Use the if statement to select a statement for execution based on the value of a Boolean expression:
if (temperatureSum > 0) { averageTemperature = temperatureSum / temperatures.Count; } else { averageTemperature = this.Temperature; } |
To keep you out of trouble, execution statements should always be enclosed within curly braces.
The For Statements:
Use the for statement only when a variable runs from somewhere with some constant increment or decrement:
for (int iCount = 0; iCount < temperatures.Count; iCount ++) { temperatureSum += (int) temperatures[iCount]; } |
As for the if statement, execution statements should always be enclosed within curly braces.
The ForEach Statement:
Use the foreach statement to iterate through collections that do not need to be changed:
foreach (int temperature in temperatures) { temperatureSum += temperature; } |
As for the for statement, execution statements should always be enclosed within curly braces.
Note
Using the foreach statement to change a collection may cause unpredictable side effects.
The While Statement:
Use the while statement to execute a statement until a specified expression evaluates to false:
while (true) { ... if (DetectTemperature != null) { DetectTemperature(this, args); } ... } |
As for the foreach statement, execution statements should always be enclosed within curly braces.
Note
If the specified expression never evaluates to true, the statement will never be executed.
The Do While Statement:
Use the do statement to execute a statement repeatedly until a specified expression evaluates to false, at least one time even if the expression never evaluates to true:
do { ... line = Console.ReadLine(); switch (line) { ... case CommandExit: exit = true; break; ... } } while (!exit); |
As for the while statement, execution statements should always be enclosed within curly braces.
The Switch Statement:
Do not hardcode numbers. Use constants instead. Do not hardcode strings. Use resource files. Avoid using many member variables. Declare local variables and pass them to methods instead of sharing a member variable between methods. If you share a member variable between methods, it will be difficult to track which method changed the value and when. Use enum wherever required. Do not use numbers or strings to indicate discrete values.
//Good:
enum MailType { Html, PlainText, Attachment } void SendMail (string message, MailType mailType) { switch ( mailType ) { case MailType.Html: // Do something break; case MailType.PlainText: // Do something break; case MailType.Attachment: // Do something break; default: // Do something break; } } |
//Not good:
void SendMail (string message, string mailType) { switch ( mailType ) { case "Html": // Do something break; case "PlainText": // Do something break; case "Attachment": // Do something break; default: // Do something break; } } |
Prefer ternary operator over assign variable values on if else condtion
string result; if (someString != null) { result = someString; } else { result = “Unavailable”; } return result; It should write as below return someString ?? “Unavailable”; |
Use var when the type is very obvious
Avoid unnecessary use var keyword, use var as the result of a LINQ query, or if the type is very obvious from the same statement and using it would improve readability.
//Not Good
var i = 3; // what type? int? uint? float? var myfoo = MyFactoryMethod.Create("arg"); // Not obvious what base-class or // interface to expect. Also difficult // to refactor if you can't search for // the class |
//Good
var q = from order in orders where order.Items > 10 and order.TotalValue > 1000; var repository = new RepositoryFactory.Get<IOrderRepository>(); var list = new ReadOnlyCollection<string>(); In all of three above examples it is clear what type to expect. |
Miscellaneous Tips
Numbers in names of fields, variables or members are very rarely needed. In fact, in most cases they are a lazy excuse for not defining a clear and intention-revealing name.
Don’t prefix member fields
The following rules specify how to define identifier names:
1. Namespaces must be named using Pascal casing, and their names must be nouns or noun phrases describing a logical group of classes (do not use any prefix); for example, Thermometer.
2. Classes and structs must be named using Pascal casing, and their names must be nouns or noun phrases describing behavior (do not use any prefix); for example, Thermometer. Exception classes must always have the Exception suffix; for example, OutOfRangips:eException.
3. Interfaces must be named using Pascal casing, and their names must be nouns or noun phrases refixed with I describing behavior; for example, IComponent.
4. Enumeration types and values must be named using Pascal casing, and their names must be singular nouns or plural nouns for bit fields (do not use any prefix); for example, temperatureScale.Celsius.
5. Readonly fields must be named using Pascal casing, and their names must be nouns or abbreviations’ for nouns; for example, AbsoluteZero.
6. Constant fields must be named using All Upper casing, and their names must be nouns or abbreviations’ for nouns; for example, ABSOLUTE_ZERO.
7. Parameter and non-constant fields must be named using Camel casing, and their names should be nouns or noun phrases describing the meaning of the field; for example, newTemperature.
8. Private member variables should be prefixed with ‘_’ and Camel casing.
9. Variables must be named using Camel casing, and their names should describe the meaning of the variable, unless they are used in trivial counting loops; for example, sumTemperature.
10. Methods must be named using Pascal casing, and their names must be verbs or verb phrases; for example, OnDetectTemperature().
11. Properties must be named using Pascal casing, and their names must be nouns or noun phrases describing the meaning of the property (consider naming properties like the attributes they represent); or example, AverageTemperature.
12. Events must be named using Pascal casing, and their name should be verbs or verb phrases describing the event; for example, DetectTemperature.
13. Event handlers must be named using Pascal casing, and their names should be the same as the name of the events they handle with the EventHandler suffix.
14. Event handlers must always have two parameters named sender and args, respectively, and event argument classes should always have the EventArgs suffix:
15. Type Parameter must be named using Pascal casing, and their names must be nouns or noun phrases with prefix T. for example TView
Avoid acronyms where ever possible in naming anything.
<> int averageTemp = 10; // Avoid int avgTmp = 10; // Avoid int averageTemprature = 10; // Right way. |
Name methods using verb-object pair
Name methods using a verb-object pair such as ShowDialog. A good name should give a hint on thewhat of a member, and if possible, the why. Also, don’t include And in the name of the method. It implies that the method is doing more than one thing, which violates the single responsibility principle.
interface IEmployeeRepository { //Not Good Employee[] First() { } //Good Employee[] GetFirstFive() { } |
Properly name properties
· Do name properties with nouns, noun phrases, or occasionally adjective phrases.
· Do name boolean properties with an affirmative phrase. E.g. CanSeek instead of Cant Seek.
· Consider prefixing Boolean properties with Is, Has, Can, Allows, or Supports.
· Consider giving a property the same name as its type. When you have a property that is strongly typed to an enumeration, the name of the property can be the same as the name of the enumeration. For example, if you have an enumeration named CacheLevel, a property that returns one of its values can also be named CacheLevel.
· Do name boolean properties with an affirmative phrase. E.g. CanSeek instead of Cant Seek.
· Consider prefixing Boolean properties with Is, Has, Can, Allows, or Supports.
· Consider giving a property the same name as its type. When you have a property that is strongly typed to an enumeration, the name of the property can be the same as the name of the enumeration. For example, if you have an enumeration named CacheLevel, a property that returns one of its values can also be named CacheLevel.
Avoid short names or names that can be mistaken with other names
Although technically allowed, the following statement is quite confusing.
bool b001 = (lo == l0) ? (I1 == 11) : (lOl != 101);
bool b001 = (lo == l0) ? (I1 == 11) : (lOl != 101);
Braces:
Opening curly braces should be placed on the new line always. Keywords and closing curly
braces must always line up vertically, indentations should be clear.:
namespace Thermota.Core { ... public class Probe { ... private void Detect() { ... while (true) { ... if (DetectTemperature != null) { DetectTemperature(this, args); } ... } } } } |
However there is no need of the curly braces in a single line statement, but for best practice use the curly braces, in some condition it could be very harmful.
if(condition==true) IpAddress=”192.168.0.6”; //IpAddress=GetIpAddress(); |
When you will deploy the application in that time you will comment hardcoded value then some and uncomment second line but some time miss to delete fist line and without curly braces actual IP address function will not executed based on condition, ]so avoid these condition use curly braces.
Framework Guidelines:
Use C# type aliases instead of the types from the System namespace
For instance, use object instead of Object, string instead of String, and int instead of Int32. These aliases have been introduced to make the primitive types a first class citizen of the C# language, so use them accordingly,
Exception When referring to static members of those types, it is custom to use the full CLS name, e.g. Int32.Parse() instead of int.Parse().
Properly name identifiers referring to localized resources
The guidelines in this topic apply to localizable resources such as error messages and menu text.
• Use Pascal casing in resource keys.
• Provide descriptive rather than short identifiers. Keep them concise where possible, but don’t sacrifice readability.
• Use only alphanumeric characters in naming resources.
Don’t hardcode strings that change based on the deployment
Examples include connection strings, server addresses, etc. Use Resources, the ConnectionStrings property of the ConfigurationManager class, or the Settings class generated by Visual Studio.
Build with the highest warning level
Configure the development environment to use Warning Level 4 for the C# compiler, and enable the option Treat warnings as errors. This allows the compiler to enforce the highest possible code quality.
Use Extension method and avoid LINQ for simple expressions
Example:
var query = from item in items where item. Length > 0; |
Prefer using the extension methods from the System.Linq namespace.
var query = items.Where(i => i.Length > 0); |
Since LINQ queries should be written out over multiple lines for readability, the second example is a bit more readable.
Use Lambda expressions instead of delegates
Lambda expressions have been introduced in C# 3.0 and provide a much more elegant alternative for anonymous delegates. So instead of
Customer c = Array.Find(customers, delegate(Customer c) Coding Guidelines for C# 3.0 and C# 4.0 { return c.Name == “Tom”; }); use an Lambda expression: Customer c = Array.Find(customers, c => c.Name == “Tom”); Or even better var customer = customers.Where(c => c.Name == “Tom”); |
Return an IEnumerable<T> or ICollection<T> instead of a concrete collection class
In general, you don’t want callers to be able to change an internal collection, so don’t return arrays, lists or other collection classes directly. Instead, return an IEnumerable<T>, or, if the caller must be able to determine the count, an ICollection<T>.
ref : http://www.stackdotnet.com/2011/12/c-coding-guidelines-and-best.html
No comments:
Post a Comment