5

I often see in C# code the following convention:

some_type val;
val = something;

like

DataTable dt;
dt = some_function_returning_datatable();

or

DataTable dt = new DataTable();
dt = some_function_returning_datatable();

instead of

some_type val = something;
DataTable dt = some_function_returning_datatable();

I initially assumed that this was a habit left over from the days when you had to declare all local variables at the top of the scope. But I've learned not to dismiss so quickly the habits of veteran developers.

(In my 3rd code section will it not be wastage of memory when we assign dt first with new and then from function)

So, is there a good reason for declaring in one line, and assigning afterwards?

Nikhil Agrawal
  • 47,018
  • 22
  • 121
  • 208

5 Answers5

18

In my 3rd code section will it not be wastage of memory when we assign dt first with new and then from function

Yes, it will indeed. Only relatively minor - creating a useless DataTable object - but still wasteful and unclear.

So, is there a good reason for declaring in one line, and assigning afterwards?

Only if you don't have the value immediately. For example:

string x;
if (someCondition) {
    // Do some work
    x = someResult;
} else {
    // Do some other work
    x = someOtherResult;
}

Often this can be improved either using a conditional operator or extracting that code into a method. Sometimes it doesn't work out that way though.

For simple situations of:

Foo x = SomeInitializationWithNoUsefulSideEffects();
x = SomeUsefulValue();

Or

Foo x;
x = SomeUsefulValue();

You should absolutely refactor to

Foo x = SomeUsefulValue();

One other interesting situation where the declaration point does make a difference is in captured variables, although normally not the way it's intended:

int x;
for (int i = 0; i < 10; i++) {
    x = SomeFunction();
    actions.Add(() => Console.WriteLine(x));
}

vs

for (int i = 0; i < 10; i++) {
    int x = SomeFunction();
    actions.Add(() => Console.WriteLine(x));
}

In the first snippet, each delegate will capture the same variable, so they would all effectively see the last value returned from SomeFunction. In the second snippet, each delegate will capture a separate "instance" of x.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • is there any cost for a non assigned reference? – Sleiman Jneidi May 08 '12 at 10:41
  • @sleimanjneidi: It's not clear what you mean. "non assigned reference" isn't a term I understand. – Jon Skeet May 08 '12 at 10:42
  • @JonSkeet string s; by itself without creating an object – Sleiman Jneidi May 08 '12 at 10:43
  • @sleimanjneidi: Okay, so that's a *variable*, not a reference. Assuming it's used somewhere else - so it can't be optimized out entirely - it'll take the same storage space (whether that's on the stack or the heap) regardless of when it's initialized. – Jon Skeet May 08 '12 at 10:45
  • 5
    @ubercooluk - no. Vote for the **post** not the **user**. Yes it has a good change of being correct ;), but evaluate the post on it's own merits. – ChrisF May 08 '12 at 10:48
  • Yes, people also do that when they want to assign `x` inside a `switch` statement (where using conditional operators `?:` would not be appropriate). – Jeppe Stig Nielsen May 08 '12 at 10:50
9

But I've learned not to dismiss so quickly the habits of veteran developers.

Dismiss them very quickly without worrying or any hesitation. It's completely meaningless to write in C#:

some_type val;
val = something;

instead of:

some_type val = something;

or:

DataTable dt = new DataTable();
dt = some_function_returning_datatable();

instead of:

DataTable dt = some_function_returning_datatable();

Anyway if you don't dismiss them in your code, the C# compiler will dismiss them when emitting the resulting IL.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • There is only reason for seperate declaration if the variable is to be used right away as a ref or out argument. – MaLio May 08 '12 at 10:39
  • +1 since the answer is from among the top 3 uses of stackoverflow although .net is not my style – coolguy May 08 '12 at 10:45
  • 2
    @ubercooluk vote for the content/answer presented and not just coz someone from the top 10 answered it. – V4Vendetta May 08 '12 at 10:47
0

Its everyone's own wish. There is no perfomance issue. Since CLR will make its own declaration how ever you declare, whether it is in one line or two line.

I always follows

int i=5;

where ever possible.

but be sure, because when you declare int i=5; in single line, CLR has to create a new instance of integer.

Kishore Kumar
  • 12,675
  • 27
  • 97
  • 154
0
SomeType someVar;
someVar = new(SomeType);

and

SomeType someVar = new(SomeType);

are equivalents. Might be a a developer habit, may be that the split was necessary but has been re-factored out, but not completely.

SomeType someVar = new(SomeType);
someVar = GetSomeTypeFromSomewhereElse();

is at best inefficient coding in that the first instance will go out of scope having apparently done nothing. Course that depends on any side effects in the constructor. If there are some then we are going to have a long and painful chat during your peer review. :D

After that as others have said it's because someVar is must be declared so it can be assigned via some further logic.

Tony Hopkinson
  • 20,172
  • 3
  • 31
  • 39
0

When reading code, it is very useful to know which variables will change within their scope and which ones will not. A useful convention to roughly indicate this is to initialize a variable on the same line as its declaration if its value will remain constant throughout its scope, and initialize it on a line separate from its declaration if both:

  1. Its value will be reassigned within its scope, and
  2. That fact would not be immediately obvious

There's some room for judgment with regard to whether something is "immediately obvious"; some situations which would qualify would be:

  1. The initialization of the variable to something that's obviously a constant value (especially if it's the default value of the type)
  2. The reassignment of the value within a few lines of its definition
  3. The names of the variable and the initialization expression suggest loop initialization (e.g. "var currentFoo = firstFoo;")

The longer the scope of a variable, the more likely I am to use separate initialization and declaration if the value will ever change.

supercat
  • 77,689
  • 9
  • 166
  • 211