Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Some Useful Features of C#

0.00/5 (No votes)
27 Feb 2011 2  
This article discusses some useful but unknown features of C#.

Introduction

In this article, I am going to discuss some important facts which might be unknown to most developers. I am going to discuss about three different topics which are related to C# and are more helpful when building your application.

  1. Why use StringBuilder over String to get better performance
  2. Structure initialization in C#
  3. Checked operator
  4. Go To with Switch... Case

I am going to discuss the above list one by one.

Why use StringBuilder over String to get better performance

There are a number of articles and posts that say that StringBuilder is more efficient because it contains a mutable string buffer. .NET Strings are immutable, which is the reason why a new String object is created every time we alter it (insert, append, remove, etc.).

In the following section, I am going to explain this in more detail to give beginners a clear view about this fact.

I wrote the following code, and as you can see, I have defined a String variable and a StringBuilder variable. I then append a string to both of these variables:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace StringTest
{
    class Program
    {
        static void Main(string[] args)
        {
            string s = "Pranay";
            s += " rana";
            s += " rana1";
            s += " rana122";

            StringBuilder sb = new StringBuilder();
            sb.Append("pranay");
            sb.Append(" rana");
        }
    }
}

After the execution of the above code, we get:

s= "pranay rana rana1 rana12"
sb = "pranay rana"

To get in to the details of what happened when I appended the string, I used the RedGate .NET Reflector. The image below shows the IL of the code that I executed above. As you can see:

  1. The String calls the Concat(str0,str1) function to append the string.
  2. The StringBuilder calls the Append(str) function to append the string.

When I click the Concat function in Reflector, it redirects me to the code below:

As you can see, the Concat function takes two arguments and returns a String. The following steps are performed when we execute the append with the string type:

  1. Checks if the string is null or not
  2. Creates a string dest and allocates memory for the string
  3. Fills the dest string with str0 and str1
  4. Returns the dest string, which is a new string variable

So this proves that whenever I do an operation like concatenation of strings, it creates a new string because of the immutable behaviour of strings. Note: The abbove scenario occurs for all functions related to string operations.

When I click on the Append function in Reflector, it redirects me to the code below:

The Append function takes an argument of type String and returns a StringBuilder object. The following steps are performed when we execute Append with the StringBuilder type:

  1. Get the string value from the StringBuilder object
  2. Check if it is required to allocate memory for the new string we are going to append
  3. Allocate memory if required and append the string
  4. If not required to allocate memory, then append the string directly to the existing allocated memory
  5. Return the StringBuilder object which called the function, by using the this keyword

So it returns the same object without creating a new one.

Summary

I hope this section has helped you to understand the inner details of why we should use a StringBuilder over a String to get better performance when we are doing major string manipulation in your code.

Structure Initialization in C#

Structures in C# allow us to group variables and methods. Its somewhat similar to classes but there are a number of differences between them. In this article, I am not going to discuss about that. I am going to explain how to initialize a structure.

Facts

  1. A structure is a value type
  2. It doesn't allow to create a parameter less constructor because it initializes the variable with default values

Now consider the below case where I have created two structures:

Structure 1: with public members

public struct StructMember
{
    public int  a;
    public int  b;
}

Structure 2: with properties

public struct StructProperties
{
       private int a;
       private int b;

       public int A
       {
               get
               { return a; }
               set
               { a = value; }
       }

       public int B
       {
               get
               { return b; }
               set
               { b = value; }
       }
}

Considering the above two facts, I tried to use both the structures as below:

public class MainClass
{
    public static void Main()
    {
       StructMembers MembersStruct;

       StructProperties PropertiesStruct;

       MembersStruct.X = 100;
       MembersStruct.Y = 200;

       PropertiesStruct.X = 100;
       PropertiesStruct.Y = 200;
    }
}

After doing this, when I try to compile the code, I receive the following error:

The C# compiler issues the following error:
error CS0165: Use of unassigned local variable  'PropertiesStruct'

The C# compiler informs us that it allows to use the first structure without an error, but does not allow to use the second structure which exposes the property. To resolve the issue, I wrote the below line of code to initialize the second structure:

StructProperties PropertiesStruct = new  StructProperties();

And after doing this, when I compile the code, it gets complied successfully.

To find out the reason why it worked without an error when I wrote the second line, I reviewed the code under the dissembler ILDSAM and found that the property of the second structure gets implemented as a public function in MSIL.

Dissembled code

The fact is that the struct can be instantiated without using the new operator. If you do not use new, the fields will remain unassigned and the object cannot be used until all the fields are initialized.

In .NET, all simple types are structures so when you write code in C#, consider the case below where I am creating an integer variable:

int a;
Console.WriteLine(a);

The compiler raises an error that you cannot use a variable without initializing it. So you need to write either:

Default constructor assigns the value 0 to myInt

int a =0;

or

Use the new operator to call the default constructor and assign the default value to the variable

int a = new int();

Summary

It's very important to initialize a structure properly.

Checked operator

In the following section, I am going to explain about the Checked operator available in C# .NET to handle integer overflows.

Problem

In my order management system, I have to calculate the sales point for each customer who places an order. Sales points are integer values which get earned by the customer based on the products they purchase and gets deducted from the account as they purchase new products using these points. But there are some customers who are not aware of the point system or do not consume these points so that the points accumulate to more than the limit of integer variables, i.e., 2^32. So whenever a calculation takes place, I receive some junk value for those customers who have point values more than the maximum allowed integer value.

Solution

To avoid this issue of overflow of integer values and to inform customers about their points, I use the Checked operator of C# .NET.

The Checked operator is for checking for overflow in Mathematical operations and conversions for integer types.

Syntax

Checked( expression )

or

Checked { statements...... }

Example

public static void Main()
{
   int a;
   int b;
   int c;

   a = 2000000000;
   b = 2000000000;
   c = checked(a+ b);
   System.Console.WriteLine(Int1PlusInt2);
}

When we run the above code, it throws an exception as below:

Exception occurred: System.OverflowException: An exception of type
System.OverflowException was thrown.

which tells that c is more than the maximum allowed integer value.

The same way, in my application, I catch the overflow exception thrown when calculating order point,s and then send a mail to the customer reminding them to utilise the points they have, and letting them know they will lose the points after an xyz period and display the point as maxvalue+.

Go To with Switch.. Case

Go To

Allows us to jump unconditionally when required and is not recommended to be used heavily.

Switch..Case

Allows to execute a Case block based on the value of a variable, i.e., allows to do condition based programming.

Problem

In my application, I reached a stage where I had to execute code of Case 1 of a Switch..Case and if some condition was satisfied, I had to execute the code for Case 3 of the Switch..Case.

Example

Switch(myvariable)
{
    case 1:
        //statements
        …........
        if ( expression )
            execute case 3:
        break;

    case 2:
        …..
        break;

    case 3:
        …......
        break;
}

Solution

The first solution to this problem is to copy the code of Case 3 and put it in the if block of Case 1.

case 1:
    //statements
   …........
   if ( expression )
     //code of case 3
   break;

But the problem with the above solution is that it makes redundant code.

The second solution is to create a function and put the code in that and then execute the code.

case 1:
    //statements
   …........
   if ( expression )
     Case3Code();
   break;

function Case3Code()
{
 ….
}

The problem with this solution is that I have to create an extra function which is not needed.

The third solution is to make use of a Go To in the Switch..Case block:

switch(MyVariable)
{
    case 1:
        //statements
        …........
        if ( expression )
            goto case 3:
        break;

    case 2:
        …..
        break;

    case 3:
        …......
        break;
}

The Go to in the Switch..Case allows me to do the code easily and in a maintainable way.

Summary

I hope you enjoyed reading about the above features. I am going to continue this series as I get new things to add to this list.

History

  • 16 February, 2011: Initial version.
  • 27 February, 2011: Updated article.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here