This is not on par with clubbing baby seals to death, but why have a separate line of code to declare and initialize a variable, only to unconditionally set it and not check the result a bit later?

I started coding C in 1984, I understand that many programmers are used to seeing all the variables declared at the top of a method or block and feel uncomfortable doing anything else, but I think they ought to get over it. Silly code bloat is, well, silly.

Re: Make sure it's initialized!

I see one reason to split them, and it is a good one. Thing is, it doesn't apply here.

When using try catch blocks, you want the assignment of the variable within the try, just in case, especially if it is assigned by something other than a simple static value. You want to declare the variable above the try block. Here is why:

When a variable is assigned above the try it is seen within the catch and finally blocks for cleanup, setting to nothing if needed, and calling dispose in case of an error. If the variable is declared within the try block, then it is out of scope in the catch and finally. So in cases like this you want to declare on one line above the try, but assign within the try. This does not apply to simple types such as strings or integers or really anything that doesn't need a dispose.

CAPTCHA? We ain't got no CAPTCHA. We don't need no CAPTCHA. We don't need no stinking CAPTCHA!

Re: Make sure it's initialized!

Not good enough if you actually need to do something in the case of an exception with those instances or need to return the instance you are working with. You will be outside the using block and even the try block so they won't be there in the catch or finally. When you need to do this, you need to declare outside the try block so you can work with it inside the block. If you have a finally block you should not be trying to return from within the try, pass the reference back under the finally or outside of the entire exception block itself.

CAPTCHA? We ain't got no CAPTCHA. We don't need no CAPTCHA. We don't need no stinking CAPTCHA!

Re: Make sure it's initialized!

Meh. I consider it good practice to declare your variables at the top of the method. Some style checking tools even have rules for it. 1/10

Is the practice intrinsically good, or is it that you are stuck in an unproductive rut of writing cluttered, unclear code?

EVERY style check I use or know of recommends declaring as close as possible to the point of first usage, NEVER at the top of the method. In some languages declarations at the top may have a negative performance impact. Can you provide ONE concrete example of a modern (within 3-5 years) style checker that recommends declaration at top instead???

Re: Make sure it's initialized!

Meh. I consider it good practice to declare your variables at the top of the method. Some style checking tools even have rules for it. 1/10

Is the practice intrinsically good, or is it that you are stuck in an unproductive rut of writing cluttered, unclear code?

EVERY style check I use or know of recommends declaring as close as possible to the point of first usage, NEVER at the top of the method. In some languages declarations at the top may have a negative performance impact. Can you provide ONE concrete example of a modern (within 3-5 years) style checker that recommends declaration at top instead???

Re: Make sure it's initialized!

I've heard there are languages that redeclare/reinitialize variables when declaring them inside of a loop. I don't know what those are or how true it is, but it's certainly not true about C#. Declaring them at the top of the function is bad form and hard to read. Declaring stuff outside a try/catch is fine if you need it, but that's not the case here, and is also not the case for calling Dispose... you can do that without having to declare it somewhere else. You can return an instance from inside a using or try/catch.

Re: Make sure it's initialized!

I've heard there are languages that redeclare/reinitialize variables when declaring them inside of a loop. I don't know what those are or how true it is, but it's certainly not true about C#. Declaring them at the top of the function is bad form and hard to read. Declaring stuff outside a try/catch is fine if you need it, but that's not the case here, and is also not the case for calling Dispose... you can do that without having to declare it somewhere else. You can return an instance from inside a using or try/catch.

ok try this, yes going to be in VB just because:

Try

dim rs as new recordset

catch

'who cares its an example

finally

rs.dispose

When you get to the dispose you will get an object not declared error, this is .Net itself so VB or C# doesn't matter here, but goes to show that you will need to declare the record set before the try in order to reference it in the finally in order to dispose. Granted this pattern is not always needed, but when it is needed for whatever reason you need to separate your declarartion from your initiation. As I said before, this doesn't apply here, but is one of the few cases where I see the declaration and instantiation needing to be separated, "using" also doesn't help here.

CAPTCHA? We ain't got no CAPTCHA. We don't need no CAPTCHA. We don't need no stinking CAPTCHA!

Some languages/compilers will actually create space for x every time through the loop, making it extremely slow compared to declaring "MyBigObject x" outside the loop then creating the new object in the loop (assuming it's not the same object throughout the entire loop anyway).

Re: Make sure it's initialized!

@Kattman - Declaring a variable "just before the Try statement" is NOT the same thing as "at the beginning of the method". There are many valid use cases for the former (Dispose and using is a Red Herring), but not for the latter (consider that the try statement could be on line 50 of the method!)

Re: Make sure it's initialized!

Some languages/compilers will actually create space for x every time through the loop, making it extremely slow compared to declaring "MyBigObject x" outside the loop then creating the new object in the loop (assuming it's not the same object throughout the entire loop anyway).

Name one language (must be at least semi-mainstream, and less than 10 years since the latest version) that does that. EVERY language I know of (and I do write compilers) will allocate sufficient stack space on entry to the method (function, subroutine) to handle the worst case variable allocation at any point in time. The same physical memory location will be used for different variables within the same method wit no "create space" operations being performed, provided that the lifetimes of the variables permit it.

Re: Make sure it's initialized!

Some languages/compilers will actually create space for x every time through the loop, making it extremely slow compared to declaring "MyBigObject x" outside the loop then creating the new object in the loop (assuming it's not the same object throughout the entire loop anyway).

Well, with the sort of code you wrote, yes, I'd expect a compiler to create a new object each time you told it to. A super smart compiler might be able to convince itself that PerformAction() doesn't change the state of x, and just reuse it, but I wouldn't rely on that sort of thing. The time drag is calling the constructor to allocate and initialize a new instance, not the storage space for x itself. That is presumably something just sitting around on the stack (or equivalent).

If a language / compiler did this by default, without knowing that PerformAction() didn't change the state of x, then I'd say that language / compiler is broken.

Re: Make sure it's initialized!

The time drag is calling the constructor to allocate and initialize a new instance, not the storage space for x itself. That is presumably something just sitting around on the stack (or equivalent).

Does C# store objects on the stack under certain conditions? Because, last time I checked, Java always stores them on the heap. Anyway, in Java it's definitely going to grab more memory on the heap every time you call new MyBigObject(); Eventually the GC will kick in to keep you from running out of heap, though.

Re: Make sure it's initialized!

@Kattman - Declaring a variable "just before the Try statement" is NOT the same thing as "at the beginning of the method". There are many valid use cases for the former (Dispose and using is a Red Herring), but not for the latter (consider that the try statement could be on line 50 of the method!)

I agree, and this is where it comes from as so many are missing. The point being, sometimes it is appropriate to declare and initialize on two separate lines considering scope. The other poster that said "Hey look!" because he went with Using also is trying to just poke the bear when hopefully he understands he is totally wrong in the case I am talking about.

Yes using will dispose, but what if it is the variable you are returning? What if you need to clean up something in the catch? Using will prevent this as I stated before because you are out of scope. And once again before somone else tries being an idiot, this is not the common case, most times yes, declare and instantiate together, use using when you can, but in those cases where you need something outside of a limited scope, then declare first, then instantiate near where you are using it. It doesn't matter if the try is 50 lines in or right at the top, if you need to reference the variable across a broader scope then give yourself the ability to do so.

CAPTCHA? We ain't got no CAPTCHA. We don't need no CAPTCHA. We don't need no stinking CAPTCHA!

Re: Make sure it's initialized!

The time drag is calling the constructor to allocate and initialize a new instance, not the storage space for x itself. That is presumably something just sitting around on the stack (or equivalent).

Does C# store objects on the stack under certain conditions? Because, last time I checked, Java always stores them on the heap. Anyway, in Java it's definitely going to grab more memory on the heap every time you call new MyBigObject(); Eventually the GC will kick in to keep you from running out of heap, though.

.NET (in current impementation and all previous) strores Reference Types on the Heap, Value Types and the items that HOLD the reference are stored "in the context of their containing scope". So local valuetypes and reference type variable ar on eht stack.

Re: Make sure it's initialized!

Yes using will dispose, but what if it is the variable you are returning?

using(var x = new object())

{

return x;

}

KattMan:

And once again before somone else tries being an idiot

You've got it nailed pretty good yourself.

KattMan:

The other poster that said "Hey look!" because he went with Using also is trying to just poke the bear when hopefully he understands he is totally wrong in the case I am talking about.

Hmmm, that's funny, because here's what I said

Sutherlands:

Declaring stuff outside a try/catch is fine if you need it, but that's not the case here, and is also not the case for calling Dispose...

Since you apparently can't say what you actually mean, or don't know what you actually mean, or are just ignorant, let's go over what you said in your original post on the subject:

KattMan:

When a variable is assigned above the try it is seen within the catch and finally blocks for cleanup, setting to nothing if needed, and calling dispose in case of an error. If the variable is declared within the try block, then it is out of scope in the catch and finally. So in cases like this you want to declare on one line above the try, but assign within the try. This does not apply to simple types such as strings or integers or really anything that doesn't need a dispose.

You don't need to clean up a variable in the finally, as I've shown. You don't need to set it to nothing. It's already calling dispose.

The only reason you would want to declare the variable outside of the try is if you need to access it in the catch for something OTHER than calling dispose, perhaps logging (or if you need it later in the function).

Also, the OP said "here are lines right after the other where they declare it and set to null, then set it to something else." You continued with "I see one reason to split them, and it is a good one." Your reason then had nothing to do with the code in the OP. It had to do with completely separate code. There is no reason to do the code in the OP. Your post was just a complete red herring from the beginning.

Re: Make sure it's initialized!

Name one language (must be at least semi-mainstream, and less than 10 years since the latest version) that does that.

You may have stopped reading my original post on this after the first sentence. Here's the second sentence:

Sutherlands:

I don't know what those are or how true it is, but it's certainly not true about C#.

It may be a legacy from 20 years ago for all I know. I've simply heard it as the reason to do it. My team lead did it when I first joined the team I'm on.

"I've simply heard it as the reason to do it." - So you are a Cargo Cultist then.

"My team lead did it when I first joined the team I'm on." - ALL practices should be reviewed on a regular basis. Failure to do so is the root cause of many a WTF. There have been multiple times where this conversation has occured:

Me: "Why are you doing X?"Other: "Because that is the way we have always done it."Me: "One more time, what is the current reason?"Other: "Just as I said"Me: "Well you wont be doing it any more, at least not around here..enjoy your new job when you find it...good day."

Re: Make sure it's initialized!

Name one language (must be at least semi-mainstream, and less than 10 years since the latest version) that does that.

You may have stopped reading my original post on this after the first sentence. Here's the second sentence:

Sutherlands:

I don't know what those are or how true it is, but it's certainly not true about C#.

It may be a legacy from 20 years ago for all I know. I've simply heard it as the reason to do it. My team lead did it when I first joined the team I'm on.

"I've simply heard it as the reason to do it." - So you are a Cargo Cultist then.

"My team lead did it when I first joined the team I'm on." - ALL practices should be reviewed on a regular basis. Failure to do so is the root cause of many a WTF. There have been multiple times where this conversation has occured:

Me: "Why are you doing X?"Other: "Because that is the way we have always done it."Me: "One more time, what is the current reason?"Other: "Just as I said"Me: "Well you wont be doing it any more, at least not around here..enjoy your new job when you find it...good day."

Wow, you sure think you know a lot about me. I'm the one who got the team to stop doing that. I also suggested when I was on the team before that to use consts and inline functions instead of #DEFINEs (in C++). What you apparently fail to grasp is not everyone is in the position of power that you have with your 30 years experience, or whatever it is. Some of us don't have the power to say "you won't be doing it anymore" and instead are in the position where people tell me (this actually happened) "that's how we do it. Give it a few months and then if you want to start making suggestions we'll talk about them." But thanks for the advice, I'll be sure to listen to it... well, never, because I already do what I can do improve the practices of my team.

Re: Make sure it's initialized!

Re: Make sure it's initialized!

Wow, you sure think you know a lot about me. I'm the one who got the team to stop doing that. I also suggested when I was on the team before that to use consts and inline functions instead of #DEFINEs (in C++). What you apparently fail to grasp is not everyone is in the position of power that you have with your 30 years experience, or whatever it is. Some of us don't have the power to say "you won't be doing it anymore" and instead are in the position where people tell me (this actually happened) "that's how we do it. Give it a few months and then if you want to start making suggestions we'll talk about them." But thanks for the advice, I'll be sure to listen to it... well, never, because I already do what I can do improve the practices of my team.

I do not know anything about you (except from that wou have posted here), and I can not concieve of a reason for you to think otherwise. You are correct that "Some of us don't have the power to say "you won't be doing it anymore"", in fact, I would think that most do not. I am indeed fortunate that I own the company where I do [and this has very little to do with how much experience I have today, as I formed the company when I only had about 8 years of professional experience].

But, everyone does have the power to say "I will not be doing that" (unless an indentured person on some third world country) Yes there will be ramifications, especially in todays market, but it comes down to a persons beliefs and ethics. I am not saying that everyone "should" take such a position, simply that it is their choice.

Re: Make sure it's initialized!

The time drag is calling the constructor to allocate and initialize a new instance, not the storage space for x itself. That is presumably something just sitting around on the stack (or equivalent).

Does C# store objects on the stack under certain conditions? Because, last time I checked, Java always stores them on the heap. Anyway, in Java it's definitely going to grab more memory on the heap every time you call new MyBigObject(); Eventually the GC will kick in to keep you from running out of heap, though.

.NET (in current impementation and all previous) strores Reference Types on the Heap, Value Types and the items that HOLD the reference are stored "in the context of their containing scope". So local valuetypes and reference type variable ar on eht stack.

Yes, that was my point. Basically that the reference (probably a pointer, of course, but that's just an implementation detail) held by x will be on the stack. The "storage space for x" was just the reference. Obviously, value type stuff (in languages that have that sort of thing) will complicate matters, but is out of scope of this particular conversation.

Re: Make sure it's initialized!

So your still have declared your recordset outside the try block that handles the dispose. Only you have introduced 2 try blocks now.

No, I haven't. I wrote a using block and correctly used it to clean up the resources of the recordset while making the code easy to read. I don't give a flying crap what the IL does, or whether it's the same as what you wrote. It was stated "you will need to declare the record set before the try in order to reference it in the finally in order to dispose." I showed that, no, you don't, and I wrote code that did it the correct way. Are you dense?

Re: Make sure it's initialized!

Right, my post goes on the outside of the quote tags. Let's pretend it looked something like this:

Sutherlands:

pkmnfrk:

Sutherlands:

KattMan:

Yes using will dispose, but what if it is the variable you are returning?

using(var x = new object())

{

return x;

}

Not only will this not compile (System.Object doesn't have a Dispose method), but writing code like this is justifcation to break out the stabbings at my place of work.

I'm not sure what you're saying, exactly, but you make me look at it and say "this isn't even a valid scenario, since it will dispose of the object and you won't be able to use it."

It's a perfectly valid scenario, from the compiler's point of view. The compiler will happily ensure that Dispose is called on the object just before it gets returned. If you need to return IDisposable objects, you don't put them in using blocks.