When declaring a member which will hold a constant value, I have seen instances there are folks who use ‘const’ and also there are folks who loves to use ‘static readonly’. There are debates over it, which one is the correct way to follow … looking down inside(MSIL level ), here is what I found.
Let us consider, we are writing a Library and we have declared two variables in a public class as mentioned below …
public static readonly int ReadOnlyStatic = 100;
public const int ReadOnlyConst = 100;
Now let us create a Console Application which will have a reference of the above library, and in the Main method we write the following code block…
static void Main(string[] args)
{
int _staticReadonly = TestClass.ReadOnlyStatic;
int _const = TestClass.ReadOnlyConst;
Console.WriteLine("Constant:{0}, ReadOnlyStatic:{1}", _const, _staticReadonly);
If we do ILDASM of the codeblock, here is what we will found ….
.locals init ([0] int32 _staticReadonly,[1] int32 _const)
IL_0001: ldsfld int32 [POC_ConstantVsReadOnly]POC_ConstantVsReadOnly.TestClass::ReadOnlyStatic
IL_0006: stloc.0
IL_0007: ldc.i4.s 100
IL_0009: stloc.1
So, it’s clear from the MSIL that in case of const, the compiler assign(hardcode) the value into the variable( refer to the second underlined statement), and in case of static readonly it refers to the class member(refer to the first underlined statement).
What does that mean ? That means for some reason if we change the value of constant in the Library we have to recompile all the assemblies which have a reference to this library, however if we change the value of static readonly and then we would be fine if we just replace the compiled library in the referenced assemblies Bin folder.
To test this feature, let us do this:
A. Let us change the value in the Library as mentioned below and then compile the library.
public static readonly int ReadOnlyStatic = 50;
public const int ReadOnlyConst = 50;
B. Now manually replace the newly complied library in the console app Bin folder( I had set ‘copy local’ as true while having a reference of the library ) , let us run the console application( without compiling), now we will see the value of ‘const’ is 100 but the value of ‘static readonly’ as 50, now compile the Console app project, and this time both of the will show the value as 50.
So, we must remember if we declare a member as ‘const’ in a library, then upon changing the value all the dependent applications have a to release a new version just because the constant value has been changed.
What about performance ? Only on the first call, static readonly will be slower compare to const, the subsequent calls should be as good as const.
Monday, September 22, 2008
Const OR Static ReadOnly
Thursday, June 05, 2008
C# 3.0 Specifications.
· Implicitly typed local variables, which permit the type of local variables to be inferred from the expressions used to initialize them.
· Extension methods, which make it possible to extend existing types and constructed types with additional methods.
· Lambda expressions, an evolution of anonymous methods that provides improved type inference and conversions to both delegate types and expression trees.
· Object initializers, which ease construction and initialization of objects.
· Anonymous types, which are tuple types automatically inferred and created from object initializers.
· Implicitly typed arrays, a form of array creation and initialization that infers the element type of the array from an array initializer.
· Query expressions, which provide a language integrated syntax for queries that is similar to relational and hierarchical query languages such as SQL and XQuery.
· Expression trees, which permit lambda expressions to be represented as data (expression trees) instead of as code (delegates).
I reckon it should be a must read for all C# programmer(especially for those who are planning to use LINQ, cause features like Extension Method, Anonymous Type, Lamda Expression are built for LINQ, these features work as an infrastructure for LINQ )
Btw. It is just 25 pages document, so won’t be taking much time to finish it, enjoy reading .. -:)
You can find the document at http://msdn.microsoft.com/en-us/library/ms364047(VS.80).aspx#cs3spec_topic4
Monday, June 02, 2008
How JET( OLE DB) decide the Excel Column type ?
However, an interesting issue came up while using the tool in China, whenever somebody enters Chinese char thru the tool gets the ever helping error message “Multi Step generated Error, check each status value”.
While investigating the issue, it came up that the Column type is the culprit, JET was setting the column type as ADVARCHAR, and to assign a Chinese char( read UNICODE ) the column type has to be ADVARWCHAR, but the question here is how to set column type in Excel ? so how does JET decide a Column type ?
What JET do is…it scans a number of rows( default is 8, goes by the value set in Hkey_Local_Machine/Software/Microsoft/Jet/4.0/Engines/Excel/ TypeGuessRows ) for each column and decide the column type, for example a column has 8 rows with numeric data, JET will set the data type as numeric, but consider a case where a column has 3 rows with numeric data and rest 5 with char data, what will be the type of the column ? JET will set the column type as ‘VARCHAR’.
Well, this is not all, there is one more registry key which also plays a very important role here, Hkey_Local_Machine/Software/Microsoft/Jet/4.0/Engines/ Excel/ImportMixedTypes … if the value of this key is ‘Majority Type’ then in the above case JET will set the column type as VARCHAR, however if the value of ‘ImportMixedTypes’ is ‘Text’ then JET will set the column type as UNICODE VARCHAR or ADVARWCHAR( irrespective of the column values)
However, as per JET documentation, we can override the registry setting thru the Connection String, if we set IMEX=1( as part of Extended Properties), the JET will set the all column type as UNICODE VARCHAR or ADVARWCHAR irrespective of ‘ImportMixedTypes’ key value.hey
Wednesday, April 23, 2008
Meeting with Ray Ozzie
It was a house-full session, around a few thousand engineers eagerly waiting to hear from him, though I found lot of us has preferred to view this meeting thru our internal web cast. I have been in the venue long before to make sure that I will get a chair at the front row, but to my surprise the whole room was almost filled up.
He has been introduced by our Development Center Manager, Srini Kopulu, after then he has delivered a session which covered about our products, the IT industry, how we are looking at the future etc, but no doubt the best round was the question and answer session, he has answered question relates to simple technology to complex architecture/model/prototype/ideas/problems, but the best question was …
“How( or what are the qualities required ) to become the CSA of Microsoft ? J, and I found this is the only question he took little time to think before answer, cause rest of the questions were all technical.
Overall, I have found him a very simple man, looks so down to earth, and very very techie, no doubt, it will reamin a memorable day for lot of us.
Monday, April 21, 2008
CLR Profiler
Few days back I have written a tool using C# which does quite a few WIN32 native calls, and COM calls, while testing I have started doubting that may be my code has some memory leak.
To find out whether it is really leaking memory, I have taken help of a tool named ‘CLR Profiler’ written by Peter Sollich ( A CLR performance Architect), it’s a great tool in a word, it shows memory allocation( in bytes), allocation pattern, GC details, memory allocated for Large Objects …almost everything about memory management.
I found it very useful tool for checking memory leaks for the .NET apps( including ASP.NET apps/services).
While using this tool only thing to remember is that this tool takes quite a lot of memory for writing logs, and by default it writes the log into WINNT\Temp folder, perhaps the best idea would be setting this folder as non system drive( and which is having huge space ).
This tool is downloadable( with source code) , check out this link … http://www.microsoft.com/downloads/details.aspx?FamilyId=A362781C-3870-43BE-8926-862B40AA0CD0&displaylang=en.
Monday, February 11, 2008
Get the Inheritance Hierarchy of a Type
public void PrintTypeName(Type type)
{
Console.WriteLine(type.ToString());
if (type.BaseType != null)
{
PrintTypeName(type.BaseType);
}
}
We can call this method as mentioned below ….
PrintTypeName(typeof(int))
PrintTypeName("ABC".GetType())
PrintTypeName('A'.GetType())
Wednesday, February 06, 2008
int[][] vs int[ , ]
There is shuttle difference between the above array declaration …
The first one is known as ‘Jagged Array’ and the second one is a normal daily used two dimensional array J ( I don’t know whether there is any jargon for this type of array )
We can initialize the first one as follows …
int[][] jaggedArr = new int[4][];
jaggedArr[0] = new int[] { 0, 1, 2, 3 };
jaggedArr[1] = new int[] { 4, 5 };
jaggedArr[2] = new int[] { 6, 7, 8 };
jaggedArr[3] = new int[] { 9, 10, 11, 12, 13, 14, 15 };
if you look at the above declaration, all the array element is having a single dimension array, but the array length is different, jaggedArr[0] has an array of 4 elements, jaggedArr[1] has an array of 2 elements, jaggedArr[2] has an array of 3 elements …
But, when it comes to the second one, i.e. int[,], we have to initialize it as mentioned below,
int[,] intArr = new int[3, 4]{
{ 0,1,2,3 },
{4,5,6,7},
{8,9,10,11}
};
So, here also all the array element is having a single dimension array, but the array length exactly same as mentioned during initialization, the array contains by intArr[0], intArr[1], intArr[2] is having the same number of elements.
Now, the question is when to use a jagged array ? well, when we know beforehand that each array element will contain another array and the number of element of this array will vary for each outer array element.
For example, if we have an array of polygons, and each element(row) contains the vertices of the polygon, we can use a jagged array in this case, since each polygon( Square, Rectangle, etc ) have different number of vertices.
Friday, January 04, 2008
Designing new primitive types !!!
To develop a complex type( here Point type )we can create a class or a structure, and as we all know a class would be considered as Reference type, but a Structure will be considered as a Value type, or as a primitive type such as ‘int’, now how to decide whether I should go for a class or reference type …. If I think from the operation perspective, for example I want my type should be used like a primitive type, hence I would be able to write this code block ..
Point p1 = new Point(200, 100);
Point p2 = 50;
Point p3 = p1 + p2;
p3 += 10;
Console.WriteLine( "Default Format = {0}", p1 );
Console.WriteLine( ": Format = {0::}", p2 );
Console.WriteLine("Default Format = {0}", p3);
Well, we can write the above code block irrespective of ‘Point’ is a class or a structure, but writing ‘Point’ as a class could be a problem since …
a) Could be NULL[ at times this cause a problem ]
b) ‘=’ sign refer to a reference not value.
c) Heap based, accessing Stack is faster than Heap.
d) Array allocates references not Value… this could be a problem also.
Defining a Structure[ or we can say we will be able to define Point as a primitive type ] we can get rid of all the above problems, does it sound interesting ? if so please check out Point structure code base .....
public struct Point: IFormattable
{
const int _defaultY = 100;
private int _x;
private int _y;
public Point(int x, int y)
{
_x = x;
_y = y;
}
public int X
{
get { return _x; }
}
public int Y
{
get { return _y; }
}
public static implicit operator Point(int x)
{
return new Point(x, _defaultY);
}
public static explicit operator Int16(Point p)
{
return(Int16) p.X;
}
public static Point operator+(Point p1, Point p2)
{
return new Point((p1.X + p2.X), (p1.Y + p2.Y));
}
public static bool operator ==(Point p1, Point p2)
{
bool flag = false;
if (p1.X == p2.X && p1.Y == p2.Y)
{
flag = true;
}
return flag;
}
public static bool operator !=(Point p1, Point p2)
{
bool flag = false;
if (p1.X != p2.X && p1.Y != p2.Y)
{
flag = true;
}
return flag;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public override bool Equals(object obj)
{
return base.Equals(obj);
}
public override string ToString()
{
return "X = " + this.X + ", Y = " + this.Y;
}
#region IFormattable Members
public string ToString(string format, IFormatProvider formatProvider)
{
string str = this.ToString();
if (String.Compare(format, ":") == 0 )
{
str = "X:" + this.X + ",Y:" + this.Y;
}
return str;
}
#endregion
}