Use Proper Naming Conventions
You should prefer proper naming conventions for consistency of your
code. It is very easy to maintain the code if consistent naming is used
all over the solution. Here are some naming conventions which are
generally followed by .NET developers:
- Always use Camel case (A word with the first letter lowercase, and
the first letter of each subsequent word-part capitalized) while
declaring variables.
- Use Pascal (A word with the first letter capitalized, and the first
letter of each subsequent word-part capitalized) naming format while
declaring Properties.
- Avoid all uppercase or lowercase names for properties, variables or
method names. Use all uppercase when declaring const variables.
- Never use a name that begins with a numeric character.
- Always prefer meaningful names for your class, property, method,
etc. This will be very useful for you to maintain the code in future.
For example, “P” will not give proper meaning for a class. You will find
it difficult to know about the class. But if you use “Person”, you will
easily understand by it.
- Never build a different name varied by capitalization. It is a very
bad practice. It will not be useful while developing code, as you will
not know what is “person” class and what is “Person” class!!! But from
the above scenario, it can be very easily understandable that “person”
is an instance variable of “Person” class.
- Don't use the same name used in .NET Framework. People who are new to your code have great difficulty to understand it easily.
- Avoid adding prefixes or suffixes for your identifiers. Though in
some guidelines, they use “m_” and in some other they use “_” as the
prefix of variable declaration. I think it is not that much useful. But,
it depends on your organizational coding practices. This point is
contradictory based on various organizations and there is no strict
guidance on it.
- Always use “I” as prefix for Interfaces. This is a common practice for declaring interfaces.
- Always add “Exception” as suffix for your custom exception class. It will give better visibility to your exception class.
- Never prefix or suffix the class name to its property names. It will unnecessarily increase the property name. If “
Firstname
” is a property of “Person
” class, you can easily identify it from that class directly. No need to write “PersonFirstname
” or “FirstnameOfPerson
”.
- Prefix “
Is
”, “Has
” or “Can
” for boolean properties like “IsVisible
”, “HasChildren
”, “CanExecute
”. These give proper meaning to the properties.
- Don't add prefix for your controls, instead write proper name to identify the control.
Decide between Value Types and Reference Types
Whenever you need to create a type, first ask yourself a question
“What you want and Why you want it?”. If you could answer your question,
you can decide between the type you want to use. If you want to store
your data, use value types and when you want to create an instance of
your type by defining the behavior, use reference types. Value types are
not Polymorphic whereas, the Reference types can be. Value types are
most efficient in terms of memory utilization over reference types and
produce less help fragmentation & garbage. If you want to pass
values to a method implementation, decide what you want to do and based
upon your requirement, decide between value types and reference types.
Use of reference type variables actually change the original value but
use of value type will create a copy of the original variable and pass
across the method. Thus, it protects your original value from accidental
changes. Let's see them in real example. In the below code, we are
passing the variable “
i
” as value type and in the method implementation incrementing it by
10
. As it was passed by value, you will see the original value “
5
” as output of the program code.
static void Main(string[] args)
{
int i = 5;
SetValues(i);
System.Console.WriteLine("Currently i = " + i); }
static void SetValues(int x)
{
x += 10;
}
In the below code, as we are sending “
i
” as a reference, it will change the original value of “
i
” inside the method and hence you will see
15
as the output in the screen.
static void Main(string[] args)
{
int i = 5;
SetValues(ref i);
System.Console.WriteLine("Currently i = " + i); }
static void SetValues(ref int x)
{
x += 10;
}
Hence, decide before you start the implementation, else once
implemented it will be very difficult to change them over your huge
application.
Always Use Properties instead of Public Variables
Reason behind this is, it makes your code properly encapsulated in
OOPs environment. By using getters & setters, you can restrict the
user directly accessing the member variables. You can restrict setting
the values explicitly thus making your data protected from accidental
changes. Also, properties give you easier validation for your data.
Let's see a small code:
public class Person
{
public string name;
public string GetNameInLowerCase()
{
return string.IsNullOrWhiteSpace(name) ?
string.Empty : name.ToLower();
}
public string GetNameInUpperCase()
{
return string.IsNullOrWhiteSpace(name) ?
string.Empty : name.ToUpper();
}
}
In the above example, you will see you have to check every time for the
Null
value as somebody from outside can easily change the value accidentally
and create a Bug in your code. If you don't want that Bug in your code,
what you will do is, use the property implementation of the variable
(making it
private
) and then access the property. This gives more reliability over your code. Let’s see an example:
public class Person
{
public string name;
public string Name
{
get
{
return string.IsNullOrWhiteSpace(name) ? string.Empty : name;
}
set { name = value; }
}
public string GetNameInLowerCase()
{
return Name.ToLower();
}
public string GetNameInUpperCase()
{
return Name.ToUpper();
}
}
Now in this case, you don't have to think about checking the value against
Null
every time. The getter implementation of the property will take care of
it. So, once implementation but use in multiple places. So, if someone
explicitly sets the “
Name
” property to
null
, your code will have no impact on it. This is just a sample code to discuss with you about the need of property instead of
public
member variable. Actual implementation may vary based on your requirement.
public class Person
{
public string Name { get; private set; }
public string Age { get; }
}
If you don't want anybody to set the Property explicitly from
outside, you can just only implement the getter inside the property
implementation or mark the setter as
private
. Also, you can implement the properties from any interface, thus gives you more OOPs environment.
Use Nullable Data Types Whenever Required
Sometimes, you may need to store
null
as the value of an
integer, double or boolean variable. So how can you do this? The normal
declaration doesn't allow you to store the
null
as value.
C# now has the feature of nullable data types. Just a small change in
your declaration. That’s it!!! You are good to go for storing
null
values. Only you have to use the “?” modifier. You have to place it
just after the type. To define an integer, you would normally do the
following declaration:
int index = 0;
To convert this as an nullable data type, you have to modify a bit to declare like this:
int? index = null;
Once you add the “?” modifier to the data type, your variable will become nullable and you will be able to store “
null
” value to it. Generally it is helpful when used with the boolean values.
Prefer Runtime Constants over Compile time Constants
Runtime constants are always preferred than the Compile time
constants. Here you may ask what is runtime constant and what is compile
time constant. Runtime constants are those which are evaluated at the
runtime and declared with the keyword “
readonly
”. On the other side, compile time constants are
static
, evaluated at the time of compilation and declared with the keyword “
const
”.
public readonly string CONFIG_FILE_NAME = "web.config"; public const string CONFIG_FILE_NAME = "web.config";
So, what is the need to prefer
readonly
over
const
variables? Compile time constants (
const
)
must be initialized at the time of declaration and can’t be changed
later. Also, they are limited to only numbers and strings. The IL
replaces the
const
variable with the value of it over the
whole code and thus it is a bit faster. Whereas, the Runtime constants
(readonly) are initialized in the constructor and can be changed at
different initialization time. The IL references the readonly variable
and not the original value. So, when you have some critical situation,
use
const
to make the code run faster. When you need a reliable code, always prefer
readonly
variables.
Prefer “is” and “as” Operators While Casting
It is better to use “
is
” and “
as
” operator
while casting. Instead of Explicit casting, use the Implicit casting.
Let me describe to you with the example of a code.
var employee = (Employee) person;
In the above code, suppose your person is a
Customer
type and when you are converting it to
Employee
type, it will throw
Exception
and in that case, you have to handle it using
try{} catch{}
block. Let’s convert the same using “
is
” and “
as
” operators. See the below code:
if(person is Employee)
{
employee = person as Employee;
}
else if(person is Customer)
{
customer = person as Customer;
}
In the above code, you can see that, in the second line I am checking whether the person is a
Employee
type. If it is of type
Employee
, it will go into the block. Else if it is a
Customer
type, will go to the block at line 12. Now, convert it with the “
as
” operator, as shown in line 5. Here, if it is unable to convert, it will return as
null
but will not throw any exception. So, in the next line, you can check whether the converted value is
null
. Based on that, you can do what you want.
Prefer string.Format() or StringBuilder for String Concatenation
Any operation in the
string
will create a new object as
string
is a mutable object. If you want to concatenate multiple
string
s, it is always better to use
string.Format()
method or
StringBuilder
class for the concatenation.
string str = "a";
str += "h";
str += "s";
str += "a";
str += "n";
Console.WriteLine(str);
In case of
string.Format()
, it will not create multiple objects instead will create a single one.
StringBuilder
as an immutable object will not create separate memory for each
operation. So your application memory management will not be in critical
stage. Hence, it is always preferable to do such operations either
using
string.Format()
or
StringBuilder
.
The above code will create a new
string
object whenever we add a new
string
there. Using
string.Format()
, you can write the following code:
string str = string.Format("{0}{1}{2}{3}{4}", "a", "h", "s", "a", "n");
If you want to use
StringBuilder
, here is the code for you:
StringBuilder sb = new StringBuilder();
sb.Append("a");
sb.Append("h");
sb.Append("s");
sb.Append("a");
sb.Append("n");
string str = sb.ToString();
The above two examples will use the same instance of the
string
every time.
Use Conditional Attributes When You Need Them
Conditional attributes are very helpful when you want to do something
only for the debug version. I know something came into your mind, the
#if
/
#endif
block. Yes, you can use the
#if
/
#endif
blocks to do something specific to the debug version like tracing or
printing something to the output screen. Then why shouldn’t we use them?
Of course, you can do that. But, there are some pitfalls. Suppose you
wrote the following code:
private void PrintFirstName()
{
string firstName = string.Empty;
#if DEBUG
firstName = GetFirstName();
#endif
Console.WriteLine(firstName);
}
In this case, it will work perfectly while in debug mode. But, see the other side. When it goes to production, the
GetFirstName()
will never get called and hence it will print an empty
string
.
That will be a Bug in your code. So, what to do? We can use the
Conditional Attribute to overcome this issue. Write your code in a
method and set the attribute of type Conditional with DEBUG string. When
your application runs in debug mode, it will call the method and in
other case, it will not. Let’s see the code here:
[Conditional(“DEBUG”)]
private void PrintFirstName()
{
string firstName = GetFirstName();
Console.WriteLine(firstName);
}
The above code actually isolates the function with the
Conditional
attribute. If your application is running under debug build, it will load the
PrintFirstName()
into memory on the first call to it. But when it will go to production
build (i.e. release build) the method will never get called and hence it
will not be loaded into memory. The compiler will handle what to do
once it gets the conditional attribute to the method. Hence, it is
always advisable to use the conditional attribute instead of the
#if
pragma blocks.
[Conditional(“DEBUG”)]
[Conditional(“TRACE”)]
private void PrintFirstName()
{
string firstName = GetFirstName();
Console.WriteLine(firstName);
}
Also, if you want to set multiple conditional attributes, you can do that by adding multiple attributes as shown above.
Use ‘0’ (zero) as Default Value Enum Value Types
While we write the
enum
definition, sometime we miss to set the
DEFAULT
value to it. In that case, it will set automatically as
0
(zero).
public enum PersonType
{
Customer = 1
}
class Program
{
static void Main(string[] args)
{
PersonType personType = new PersonType();
Console.WriteLine(personType);
}
}
For example, the above code will always print
0
(zero)
as output and you have to explicitly set the default value for it. But
if we change it a bit and add the default value, it will always print
the default value instead of
0
(zero).
public enum PersonType
{
None = 0,
Customer = 1
}
class Program
{
static void Main(string[] args)
{
PersonType personType = new PersonType();
Console.WriteLine(personType);
}
}
In this case, it will print “
None
” to the output screen. Actually the system initializes all instances of value type to
0
. There is no way to prevent users from creating instance of value type that are all
0
(zero). Hence, it is always advisable to set the default value implicitly to the
enum
type.
Always Prefer the foreach(…) Loop
The
foreach
statement is a variation of
do
,
while
or
for
loops. It actually generates the best iteration code for any collection
you have. When you are using collections, always prefer to use the
foreach
loop as the C# compiler generates the best iteration code for your
particular collection. Have a look into the following implementation:
foreach(var collectionValue in MyCollection)
{
}
Here, if your
MyCollection
is an
Array
type, the C# compiler will generate the following code for you:
for(int index = 0; index < MyCollection.Length; index++)
{
}
In future, if you change your collection type to
ArrayList
instead of
Array
, the
foreach
loop will still compile and work properly. In this case, it will generate the following code:
for(int index = 0; index < MyCollection.Count; index++)
{
}
Just check the
for
condition. You will see a little difference there.
Array
has
Length
property and hence it generated code which calls the
Length
. But in case of
ArrayList
, it replaced the
Length
with
Count
, as
ArrayList
has
Count
which does the same thing. In other scenario, if your collection type implements
IEnumerator
, it will generate a different code for you. Let’s see the code:
IEnumerator enumerator = MyCollection.GetEnumerator();
while(enumerator.MoveNext())
{
}
Hence, you don’t have to think which loop to use. The compiler is
responsible for that and it will choose the best loop for you. One more
advantage of
foreach
loop is while looping through the
Single Dimensional or Multi Dimensional array. In case of Multi
Dimensional array, you don’t have to write multi line
for
statements. Hence, it will reduce the code you have to write. The
compiler internally will generate that code. Thus, increases your
productivity.
Properly Utilize try/catch/finally Blocks
Yes, properly utilize the
try
/
catch
/
finally
blocks. If you know that the code you wrote may throw some Exception, use the
try
/
catch
block for that piece of code to handle the exception. If you know that,
the fifth line of your 10 lines code may throw exception, it is
advisable to wrap that line of code only with the
try
/
catch
block. Unnecessary surrounding lines of code with
try
/
catch
will slow down your application. Sometimes, I noticed people surrounding every method with
try
/
catch
block which is really very bad and decreases the performance of the
code. So from now, use it only when it is required. Use the
finally
block to clean up any resources after the call. If you are doing any database call, close the connection in that block. The
finally
block runs whether your code executes properly or not. So, properly utilize it to cleanup the resources.
Catch Only that Exception that You Can Handle
It is also a major one. People always use the generic
Exception
class to catch any exception which is neither good for your application
nor for the system performance. Catch only those which you expect and
order it accordingly. Finally at the end, if you want, add the generic
Exception
to catch any other unknown exceptions. This gives you a proper way to handle the exception. Suppose, your code is throwing
NullReferenceException
or
ArgumentException
. If you directly use the
Exception
class, it will be very difficult to handle in your application. But by
catching the exception properly, you can handle the problem easily.
Use IDisposable Interface
Use
IDisposable
interface to free all the resources from the memory. Once you implement
IDisposable
interface in your class, you will get a
Dispose()
method there. Write code there to free the resources. If you implement
IDisposable
, you can initialize your class like this:
using (PersonDataSource personDataSource = DataSource.GetPerson())
{
}
After the
using() {}
block, it will call the
Dispose()
method automatically to free up the class resources. You will not have to call the
Dispose()
explicitly for the class.
Split your Logic in Several Small and Simple Methods
If methods are too long, sometimes it is difficult to handle them. It
is always better to use a number of small methods based upon their
functionality instead of putting them in a single one. If you break them
in separate methods and in future you need to call one part, it will be
easier to call rather than replicating the code. Also, it is easier to
do unit testing for the small chunks rather than a big code. So,
whenever you are writing a piece of code, first think of what you want
to do. Based upon that, extract your code in small simple methods and
call them from wherever you want. In general, a method should never be
more than 10-15 lines long.