Tuesday, October 19, 2010

Best Practices for C# Application Development

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?”. 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 produces 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, protects your original value from accidental changes. Lets 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); // will print "Currently i = 5"
}

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); // will print "Currently i = 15"
}

static void SetValues(ref int x)
{
x += 10;
}


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”. 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"; // runtime constant
public const string CONFIG_FILE_NAME = "web.config"; // compile time constant


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 change 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 change 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 you with the example of a code.

// this line may throw Exception if it is unable to downcast from Person to Employee
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 it 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:

// check if the person is Employee type
if(person is Employee)
{
// convert person to Employee type
employee = person as Employee;
}

// check if the person is Customer type
else if(person is Customer)
{
// convert person to Customer type
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 the line 5. Here, if it is unable to convert, 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.

Always prefer the foreach(…) loop

Rethrow exception and InnerException property in .NET

In the example below, we have re-thrown exception with only a friendly message in the constructor method.

private void DivideOperation()
{
try
{
int x = 5;
int y = 0;
int result = x/y;
}
catch (Exception ex)
{
throw new DivideByZeroException(“Invalid operands were given.”);
}
}


This is, of course, not a good practice to do exception handling. So to preserve the details of the original exception, we have to pass the exception object as a second parameter in addition to friendly message as:

private void DivideOperation()
{
try
{
int x = 5;
int y = 0;
int result = x/y;
}
catch (Exception ex)
{
throw new DivideByZeroException(“Invalid operands were given.”, ex);
}
}

No comments: