C-Sharp : Useful tips to increase performance of program

Avoid or Reduce type casting in your program:

In your dotnet program type casting is a costly operation in program execution and you should always try to reduce casting operation especially in loops.

For example suppose you want to find all text boxes on a form and want to manipulate some property of text boxes. For this i have written following code

private void FindAllText()
{
foreach (Control item in this.Controls)
{
//In following if stmt is performs cast operation
if (item is TextBox)
{
//Here another cast.
TextBox txt = (TextBox)item;
}
}
}

In above example we are performing Control to Textbox type casting two times, we can reduce this by modifying our code as given below

private void FindAllText()
{
foreach (Control item in this.Controls)
{
//Following instance will cast control to TextBox
// and assigns null if control is not castable tp TextBox
TextBox txt = item as TextBox;
if (txt != null)
{ 
//Perform operation
}
}
}

So for better performance always try to reduce type casting.

Remove unnecessary parameters from methods :

You should always try to remove unnecessary parameter from method which are not used in method body. But this is not strict rule, you can leave unused parameter of virtual methods, delegates and event handlers because in these parameters can be used in future and in event handler method it is recommended to use first parameter as send object while it is not necessary that you are going to use this sender parameter and in future there may be requirement that you require send object .

Remove unnecessary local variables and avoid unnecessary variable assignments:

Always remove unused local variable initialization and avoid unnecessary variable assignment of variables because they increase size of assembly and reduce the performance.

private void button1_Click(object sender, EventArgs e)
{
int temp = 100;
string msg = "Some Text";
Object obj = new object();
MessageBox.Show(msg);
msg = "again assign";
}

In above example temp and obj is unused and msg is re-assigned but never used after re-assignation.

Always remove these kind of local variable and variable assignments.

Do not initialize variables unnecessarily:

CLR initializes all objects to their default values before running constructor of containing class. If you are initializing object to their default values in constructor will be redundant and reduce the performance.

Note: Framework 2.0 C# compiler automatically removes these kind of initialization.

public class MyType
{
int i;
int j;
string name;

public MyType()
{
i = 0;
j = 0;
name = null;
}

public MyType(string pname)
{
i = 0;
j = 0;
name = pname;
}
}

In above example in first default constructor i have initialized i, j and name variable to their default values which leads to redundancy because run time automatically initializes i, j and name to their default values before calling constructor.

In second constructor no need to initialize i and j with their default values.

Avoid excessive local variables:

For increase performance of program execution CLR stores values of local variable in processor register (Up to 64 including compiler generated). If no of local variables greater than 64 then variable will be stored on memory stack and it must me moved to register before manipulation and this will reduce performance.

Hence try to keep number of local variable less than 64.

Use jagged array over multidimensional array:

A jagged array is an array whose elements are arrays. The arrays that make up the elements can be of different sizes, leading to less wasted space for some sets of data.

private void ArraysTest()
{
int[][] jArray = { new int[] {1,2,3,4},
new int[] {5,6,7},
new int[] {8},
new int[] {9}
};

int[,] mdArray = {{1,2,3,4},
{5,6,7,0},
{8,0,0,0},
{9,0,0,0}
};

}

For string comparison

Use .length == 0 or .IsNullOrEmpty method.

Use static in proper way:

Always use static read only for variable which value will be initialized as run time and always make you variable constant which values is computed at compile time, using constant will increase performance in comparison to static read-only because it not required to call static constructor of class .

public class TestStatic
{
static readonly int x = 10;
static readonly double y = x + 200.5;
static readonly string s = "readonly";
static readonly DateTime dt = DateTime.Now;
}

In above example only DateTime dt is required for static read only because its value is initialized with current datetime while others are initialize with literals. It will be better to mark first three as const.

public class TestStatic
{
const int x = 10;
const double y = x + 200.5;
const string s = "readonly";
static readonly DateTime dt = DateTime.Now;
}

Above example is correct way to user static read-only and constants.

When a function is not using any non-static class member then you should mark that function static.

public class Test
{
public static readonly DateTime execStartTime = DateTime.Now;
public static readonly int size;
static Test()
{
size = Environment.SystemPageSize;
}
public int i = 10;
public static int s = 5;
public readonly int k = 5;

//Can't make static
public int getiSqr()
{
return i * i;
}

//Marked static because it is not using any
//class non-static member.
public static int add(int a, int b)
{
return a + b;
}

//Marked static because accessing static member
public static DateTime getExecStartTime()
{
return execStartTime;
}
}

Remove unused private fields in assembly. 

Remove instantiated internal classes from assembly.

Remove empty finalizers from class:

It is recommended to avoid finalizers when you can because it is over head over GC. Because GC must call finalizers before collecting object. This means two collection will be required to collect object.

Empty finalizers will be defiantly overhead without any benefit so don’t write empty finalizer in you program.

public class ClassF
{
//Don't write empty like this
~ClassF()
{ 

}
}

public class ClassG
{
//Write all debug code in
//#if DEBUG directive block
#if DEBUG

~ClassG()
{
//Debugging code
Debug.Assert(false);
}
#endif

}

Override equals and operator equals on value types:

For value types inherited equals method uses reflection to compare two objects, which is computationally expensive and that will compare every fields which may not required.

For better performance you should override Equals method and overload equality  operators == and != as given below in example.

public struct MyPoint : IEquatable<MyPoint>    
{        
private readonly int rX;        
private readonly int rY;         

public MyPoint(int x, int y)        
{            
rX = x;            
rY = y;        
}         

public int X        
{            
get { return rX; }        
}         

public int Y        
{            
get { return rY; }        
}         

public override int GetHashCode()        
{            
return rX ^ rY;        
}         

public override bool Equals(object obj)        
{            
if (!(obj is MyPoint))                
return false;             

return Equals((MyPoint)obj);        
}         

public bool Equals(MyPoint other)        
{            
if (rX != other.rX)                
return false;             

return rY == other.rY;        
}         

public static bool operator ==(MyPoint p1, MyPoint p2)        
{            
return p1.Equals(p2);        
}         

public static bool operator !=(MyPoint p1, MyPoint p2)        
{            
return !p1.Equals(p2);        
}    
}

Leave a Reply

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