The original post discussed initialization of member variables in a class, so my apologies if I go too far off topic by discussing local variables defined within the scope of a method.
Before getting into that, though, my 2 cents on the member variable initialization is this: don’t initialize variables unnecessarily; let your code do the talking. If someone needs to understand what’s going on, they can read the code for themselves. Presumably they should have enough grasp of the language to figure it out. If something is so obscure that you feel the need to clarify what’s going on by adding a line to your constructor such as “myObject = null;” or “counter = 0”, then why not add some comments instead? My initial benchmarking tests show that comments added to a constructor do not add significant performance penalty to the execution time.
One thing that kind of annoys me, however, is seeing code such as the following:
// unnecessary initialization of data variable
MyObject data = new MyObject();
// data variable is immediately assigned another value
data = CreateMyObject();
Generally I don’t make a fuss about this and if it’s early enough in the development cycle that I feel that this can be safely changed then I will remove the unnecessary constructor call. However, I see this quite frequently, and to me it seems like an indicator that the author of the code doesn’t quite fully have a grasp of what their method is doing. That last statement might seem like a bit of a stretch for me to make such a claim. Let me illustrate with a somewhat similar example:
Let’s say I am writing a function that writes out to the console the min and max values contained in an array of integers. Ordinarily I might make it a function with output parameters or something, but I am writing to the console for the sake of simplicity. Within my function I would define a min variable and a max variable, neither of which are initialized immediately:
public static void ReportMinAndMaxValues(int[] values)
{
int minValue;
int maxValue;
if (values != null && values.Length > 0)
{
minValue = maxValue = values[0];
for (int i = 1; i < values.Length; i++)
{
if (values[i] < minValue)
minValue = values[i];
if (values[i] > maxValue)
maxValue = values[i];
}
Console.WriteLine("Min Value: {0}, Max Value: {1}", minValue, maxValue);
}
else
{
Console.WriteLine("The list of values is empty, therefore there is no min value and no max value.");
}
// this line cannot compile because minValue and maxValue have not been assigned
// "It's a good thing."
//Console.WriteLine("Min Value: {0}, Max Value: {1}", minValue, maxValue);
}
I, for one, am quite glad that the C# compiler does not allow me to use minValue or maxValue until they have definitely been initialized. It would be improper for me to do so, but I feel that many people don’t quite grasp that. Instead they circumvent this compiler check by initializing a variable prematurely, such as in these two examples:
public static void ReportMinAndMaxValues_PoorExample1(int[] values)
{
int minValue;
int maxValue;
// no check for null or empty array, so an exception will be thrown
minValue = maxValue = values[0];
for (int i = 0; i < values.Length; i++)
{
if (values[i] < minValue)
minValue = values[i];
if (values[i] > maxValue)
maxValue = values[i];
}
Console.WriteLine("Min Value: {0}, Max Value: {1}", minValue, maxValue);
}
public static void ReportMinAndMaxValues_PoorExample2(int[] values)
{
int minValue = int.MaxValue;
int maxValue = int.MinValue;
if (values != null && values.Length > 0)
{
minValue = maxValue = values[0];
for (int i = 1; i < values.Length; i++)
{
if (values[i] < minValue)
minValue = values[i];
if (values[i] > maxValue)
maxValue = values[i];
}
}
// If the array is null or empty, this will incorrectly report int.MaxValue and int.MinValue as the min and max values.
Console.WriteLine("Min Value: {0}, Max Value: {1}", minValue, maxValue);
}
The problems illustrated in this example are centered around whether the values parameter is null or empty, but in general problems caused by premature variable initialization will be specific to the function in which they are used. However, I would imagine that mostly those problems would be a mis-handling of edge cases.