views:

83

answers:

4

I kind of posted a similar question a couple of days ago but that was more geared towards any *.Designer.cs file. This question is geared towards declaration and initialization of global variables within a class. To my knowledge, it's almost common practice (aside from the *.Designer.cs files it seems) to place all global variables at the beginning of a class definition followed by the rest of the code in any order (I prefer Getters and Setters, then Constructors, then Events, then misc functions). Well, I've seen it done and have done it myself where a global variable is set at declaration.

And I'm not referring to:

ClassA clA = new ClassA();

I'm referring to:

private int nViewMode = (int)Constants.ViewMode.Default;

Now, I've heard people say and I can agree with it on some levels, that the initialization of such variables, those variables that don't require a new statement when you declare the variable, should be done in constructors or initialization functions. However, when they stated that, they may have meant that the previous statements were fine, but not the following:

Wrong Way

private int nTotal = 100;
private int nCount = 10;
private int nDifference = nTotal - nCount;

Possible Right Way

private int nTotal = 100;
private int nCount = 10;
private int nDifference = 0;

void ClassConstructor()
{
  nDifference = nTotal - nCount;
}

My questions are:

What is the most common/standard practice in such a situation? What are the pros and cons of either? Are these questions only relevant for some languages and not others?

My last question I thought of as I was typing this up and here's the reason. In Visual Studio 2008 it seems I can place breakpoints on global variable declarations while I don't think I could when I used to write C++ in college. Also, I believe in college, you couldn't use a variable that was declared immediately before the current variable, but then again, that was in C++. So I'm not sure if these questions are only valid for MSVS products (we used Borland in college), newer compilers, or what not. If anyone has any insight, it's appreciated. Thanks.

+2  A: 

I believe this has been covered many times before, but there really isn't an answer other than: Whatever you do end up doing, make sure it's consistent with the code in other places in your project.

I personally prefer initializing default values outside of the constructor, unless they are calculated differently based on which constructor is used. That way, if another constructor comes along, there is no need to repeat the initialization code.

In the case of nDifference, perhaps a Property that encapsulates the logic would make more sense so:

  1. If it doesn't get used, nDifference doesn't need to get calculated every time a new instance of the class is created.
  2. It indicates the logic for nDifference should always be the same, regardless of which constructor is used.
Ocelot20
Yeah, that's what I was thinking. With different constructors, the only thing I thought would be proper is a default value rather than a calculated value. And I figured it's been asked a few times, but without having to find one that asks the question in the same way I do, I thought it'd be better to post my own. Thanks for the reply.
XstreamINsanity
+1  A: 

Personally, I like having the ability to initialize member variables where I declare them in C#, particularly if the only reason you were going to write an explicit constructor was to initialize them.

In older C# dialects (we're still on 2.0 where I work), I guess there's a consistency argument if you're populating a member Dictionary<T> or something in a constructor, since the new initializer syntax didn't show up until later. In that case, you could make the argument that you want to keep all of your initialization together. Likewise, if you're initializing some members based on constructor arguments maybe it makes more sense to keep all the initialization together rather than assigning some stuff where it's declared and other stuff in the constructor -- but if you have more than one constructor, if you don't repeat yourself you're just going to end up having some initialization in one place and the rest in another anyway so you're probably just better off assigning things where you declare them.

twon33
Yeah, I thought there might be cases where something has to be one way and not another. And that's one of the reasons I asked the question. If there are more instances of issues where something has to be initialized in the constructor as compared to at declaration, then that makes it even trickier. If it's just initializing an int to a MAX number or MIN number, then that's one thing. But initializing them to formulas and such, that might get a little out of hand. But thank you for your opinion.
XstreamINsanity
+1  A: 

I prefer to initialise all fields in the constructor rather than at point of declaration. (The only exception I make to this is for static fields where I find the addition of a static constructor overkill.) My reasons are that I like to have all of the construction logic in one place and secondly to avoid the debugger jumping around confusingly when stepping through the code. However, this is just my preference and you are free to come up with whatever convention you are most comfortable with.

As others have already stated, think your convention through carefully and apply it consistently.

Paul Ruane
Yeah, and I didn't even think about that when debugging. I think I've even seen people declare a member variable and initialized it with the return of a function. To me that just seems "spaghetti-ish." Thanks for your opinion and insight.
XstreamINsanity
+1  A: 

The C# Language Definition guarantees that field initializations will occur in textual order within each compilation unit (file). This means that it is perfectly OK to have complex expressions in the variable initializer of static field declarations. (Instance fields, on the other hand, cannot reference other instance fields.)

If the initial value of a field depends on a previous value, then they should probably be kept together to avoid accidental re-ordering.

class Demo1 {
    static int x = y + 10;  // x == 10
    static int y = 5;
}

class Demo2 {
    static int y = 5;
    static int x = y + 10;  // x == 15
}

As others have stated, I would prefer to have initializers common to all instances (regardless of the chosen constructor) to occur in the declarations.

This re-ordering behavior is only true for static variable initializers. Constant initialization occurs at compile time, and the values are calculated in an order that ensures the values are initialized correctly (and circular references for constants, unlike variables, are not allowed).

class Demo3 {
    const int x = y + 10;  // Evaluated second. x == 15
    const int y = 5;       // Evaluated first.
}

You should really consider whether a calculated value needs to be stored at all, since in many cases it can be calculated at the time it is used.

class Demo4 {
    int y = 5;
    int x { get { return y + 10; } }
}
Jeffrey L Whitledge
Thank you very much. This puts a lot of things in perspective. And believe me, I abuse getters and setters often. And it's really good to know that there is an order to things. I may have to go `const` all of my variables. :)
XstreamINsanity
Your Demo1 and Demo2 examples are invalid: these generate compilation errors. They would be valid if you were to make them static.
Paul Ruane
@Paul Ruane - Doh! You're right. I'll fix. Thanks!
Jeffrey L Whitledge