Sunday, November 20, 2005

A brief study on 'structure'

We are familiar with the concept of “structure”, and all of us must have used it many times. Most of the languages like C++, Java, VB, and of course C# and VB.NET support the concept of structure, how if we dig a little deep into this concept.

As we all know structure is a complex type, not like int or bool, but there are some more characteristics of a structure, let me explain with the context of dot net platform…..

1) Every structure is inherited from System.Object( like any class ), well, every structure is inherited from System.ValueType which inherits System.Object, hence every structure is inherited form Object.

2) Structure can not be inherited, they are like “sealed class”.

3) Structure instance are stored in the stack, and for this reason it doesn’t need any garbage collection. (well, there are exception of this rule, please read the last paragraph )

4) A structure can be boxed into a System.ValueType variable in addition to an Object variable.

5) As “Abstract” and “Virtual” are useless in case of structure(any value type ) hence can we write structure doesn’t support polymorphism ?? well I think NO, since we can do function overloading so it would be wrong to say it doesn’t support polymorphism at all.

In essence we can say that a structure is a complex type whose behavior can not extended ( the way we do it in case of class, I mean to say using inheritance we can not extend the behavior, but we can use the concept of “containment” in structure ) .

Okay .. so why do we need a structure at all when we had “class” .. because
structure has a very small footprint compare to class instance and faster in performance and no overhead of garbage collection.
There are certain situations where structure is a good candidate( compare to class ) if
1) we need a complex type and typically whose behavior doesn’t need to be extended.
2) there will be no boxing involved.


As we have mentioned above that structure doesn’t need garbage collection and we also know that structure supports “Containment” .. now what if we have a structure which contain a reference type, consider the following example …

public struct A
{
public int y;
public bool z;
}

public struct B
{
public A x;
public Book y; // Book is a class
}

In the above example structure B is contain structure A and class Book, hence when we will create an instance of “B” there will some memory allocation in the heap for the Book class instance, and when the instance of the structure B will go out of scope the memory allocated for y and z will be cleared ( from the stack ) at once, but the Book class instance will be destroyed by the garbage collection( this is an exception of characteristics 3 mentioned above ).

Tuesday, November 01, 2005

"throw" and "rethrow"

Few days back I was working on some C# code, and I found an interesting case .. all I was thing to throw an exception from an called routine to the caller and logging the exception in the caller, and I found the stack trace is not correct( more specifically the stack trace was missing some entries ).
I had to spend some time on this to find the reason behind it ... let me explain with some sample code snippet ..

private void btnTest_Click(object sender, System.EventArgs e)
{
try {
DummyMethod_1();
} catch(Exception ex) {
richTextBox1.Text = ex.GetType().ToString() + " " + ex.Message + "\n";
richTextBox1.Text += ex.StackTrace;

}
}

private void DummyMethod_1()

{
try {
DummyMethod_2();
} catch(Exception ex)
{
MyNewException e = new MyNewException ("My New exception" );
throw e;
}
}

private void DummyMethod_2()

{
ThrowException();
}

private void ThrowException()

{
int x = 0;
int y = 0;
int z = x/y;
}

btnTest is a command button and I am calling a routine from the click event of this routine, then there is a chain of routines .. which ultimately called "ThrowException" routine and which cause an exception and the "DummyMethod_1" catch the exception and send a new exception "My New Exception" to the caller ( throw e ).
I am showing the stack trace of the exception in a rich text box ...
with the above code the stack trace will look like this ...
System.Exception.MyNewException My New exception at ThrowTest.Form1.DummyMethod_1() in f:\personal\rnd\throwtest\throwtest\form1.cs:line 127 at ThrowTest.Form1.btnTest_Click(Object sender, EventArgs e) in f:\personal\rnd\throwtest\throwtest\form1.cs:line 102

All it was showing btnTest_Click::DummyMethod_1(); and the DummyMethod_1:: throw e; ... what about the DummyMethod_2 and ThrowException method ??? as they were also part of this exception in fact "ThrowException" is the routine where the exception was generated.

Then I have changed my code little bit .. instead of throw e; I modified it as throw; now the stack trace looks like this ..
System.DivideByZeroException Attempted to divide by zero. at ThrowTest.Form1.ThrowException() in f:\personal\rnd\throwtest\throwtest\form1.cs:line 140 at ThrowTest.Form1.DummyMethod_2() in f:\personal\rnd\throwtest\throwtest\form1.cs:line 133 at ThrowTest.Form1.DummyMethod_1() in f:\personal\rnd\throwtest\throwtest\form1.cs:line 127 at ThrowTest.Form1.btnTest_Click(Object sender, EventArgs e) in f:\personal\rnd\throwtest\throwtest\form1.cs:line 102

So what is the mystery of "throw e" and "throw", if we look at the MSIL , in case of thorw e .. the keyword is "throw" ... it creates a new exception( e in this case ) which has a separate stack trace altogether, but in case of thorw .. the MSIL is "rethrow" which re-thorws the existing exception, which means the stack trace will be intact.

hmmmm .. isn't it interesting ?? .. well, there is another way to tackle this situation when we will be creating a new exception we should pass the existing one as an inner exception , like this ..
MyNewException e = new MyNewException ("My New exception", ex ); and in the caller we have to look into the inner exception's stack trace as well, so the updated stack trace showing code will look like this ...
richTextBox1.Text = ex.GetType().ToString() + " " + ex.Message + "\n";
if( ex.InnerException != null )

{
richTextBox1.Text += ex.InnerException.StackTrace + "\n" + ex.StackTrace;
} else
{
richTextBox1.Text += ex.StackTrace;
}

comments are welcome !!!!