3

I'm quite unsure about using goto inside an using block.

For example:

using(stream s = new stream("blah blah blah"));
{
    //do some stuff here

    if(someCondition) goto myLabel;
}

Now if someCondition is true the code execution will move on to myLabel, but, will the the object get disposed?

I've seen some pretty good questions here on this topic but they all talk about different things.

Sean Vaughn
  • 3,792
  • 1
  • 16
  • 14
  • 3
    Why don't you check it yourself? – Leri Sep 25 '12 at 13:45
  • 9
    Are you sure you *have* to use a `goto`? ;-) – fero Sep 25 '12 at 13:45
  • 1
    You should probably avoid using goto. It's definitely not best practice. I'm sure there's some other way you can structure your code if you tell us what you're trying to do. – Neil Kennedy Sep 25 '12 at 13:46
  • 5
    `I'm quite unsure about using goto inside an using block.` - I am quite unsure about using `goto` in general, not only inside `using` blocks. – Darin Dimitrov Sep 25 '12 at 13:46
  • Yes, actually, there's no other way to move the code execution to a forward block, i've to miss out on some unnecessary lines, and `goto` seems to suit the best in my situation. @fero – Sean Vaughn Sep 25 '12 at 13:47
  • 2
    I'm surprised the creators of C# had the balls to build a high-level sophisticated programming language and then lump in *goto*. You're not programming in assembly, you know. – Neil Sep 25 '12 at 13:47
  • You can't doubt the geniuses behind C#, @Neil, `goto` has its advantages. :) – Sean Vaughn Sep 25 '12 at 13:49
  • @SeanVaughn: There are always ways to program without `goto` statements, and it as almost always advicable to do so. The use of `goto` statements complicate your code. Why not post the real code here on SO and we will show you how to refactor that code to something more maintainable without `goto`. – Steven Sep 25 '12 at 13:49
  • 1
    @SeanVaughn: Use smaller methods and use control structures instead of jumping over "unnecessary" lines. If the lines really are "unnecessary" then just remove them. – Mark Byers Sep 25 '12 at 13:49
  • 2
    `goto has its advantages. :)` - @SeanVaughn, really? I have been writing C# code for 9 years and still haven't seen a single advantage. – Darin Dimitrov Sep 25 '12 at 13:50
  • 1
    There's always some high nose that deems himself so better than others. Someone just gave me a -ve and i'm pissed now. – Sean Vaughn Sep 25 '12 at 13:50
  • 1
    @DarinDimitrov It's a good way of weeding out the unworthy CS candidates, or sticking it to annoying co-workers when you know you're leaving your job. – Servy Sep 25 '12 at 13:51
  • @SeanVaughn, I would advise you to edit this question and take another route and "*How can I avoid using goto here?*" should be the new title. (I'll add that I didn't downvote) – Neil Sep 25 '12 at 13:51
  • @DarinDimitrov, you can't doubt the geniuses behind C#. In my case I have to miss out on some lines of code, and I can not afford to use if else because nesting is deep and code readability is a priority. I'm not using many `gotos` just this one. – Sean Vaughn Sep 25 '12 at 13:52
  • 1
    @SeanVaughn If your nesting is too deep it's a sign that you should refactor sections out into their own methods. – Servy Sep 25 '12 at 13:54
  • @Servy, please expand on that. That sounds something I can do. :) – Sean Vaughn Sep 25 '12 at 13:55
  • can please someone direct me here, should I copy paste the whole code? that would be ugly. – Sean Vaughn Sep 25 '12 at 13:58
  • 1
    @SeanVaughn You find a method that's too big, you take some chunk of that code that seems like it's rather self contained, and you put it in its own method (copy paste is acceptable); use parameters and return statements as needed for data that isn't self contained. If you want, you can use the `refactor -> extract method` tool in visual studio. – Servy Sep 25 '12 at 13:58
  • 1
    @DarinDimitrov In C#, `goto` to the ONLY way to have cascading switch cases (when each case is doing some part of the code). Reference this SO question: http://stackoverflow.com/questions/12390245/falling-through-switch-statement-works-sometimes – Michael Mankus Sep 25 '12 at 13:59
  • 2
    @Neil: Although i agree that `goto` is to be avoided, this is a perfectly valid question. If you would edit the question to ask how to rewrite the code to avoid `goto`, it would better fit to [`codereview`](http://codereview.stackexchange.com/). If at all i would ask a different question. – Tim Schmelter Sep 25 '12 at 14:01
  • Exactly my thoughts @TimSchmelter, I too find it to be a very valid question. But since `goto` is so infamous among C# developers, they're missing the point here. :/ – Sean Vaughn Sep 25 '12 at 14:06
  • @DarinDimitrov, one thing as a programmer: **"Never act like you know everything."** Your 9years of C# doesn't validate you as a good programmer, and since it seems you are not aware of the advantages of `gotos`, one must come to a conclusion that your exposure to C# programming is not very deep and thus your knowledge must not be so profound. Just thought that this behavior should not be left unnoticed. :) – Sean Vaughn Sep 26 '12 at 17:04

4 Answers4

8

Yes.


But why not try it yourself?

void Main()
{
    using(new Test())
    {
        goto myLabel;
    }
myLabel:
    "End".Dump();
}
class Test:IDisposable
{
    public void Dispose()
    {
        "Disposed".Dump();
    }
}

Result:

Disposed
End

sloth
  • 99,095
  • 21
  • 171
  • 219
3

The using statement is essentially a try-finally block and a dispose pattern wrapped up in one simple statement.

using (Font font1 = new Font("Arial", 10.0f))
{
    //your code
}

Is equivalent to

Font font1 = new Font("Arial", 10.0f);
try
{
     //your code
}
finally
{
     //Font gets disposed here
}

Thus, any jump from the "try-block", be it throwing an exception, the use of goto (unclean!) &tc. will execute the Disposal of the object being used in that "finally" block..

  • 1
    Because every answer makes the same point, it's irrelevant to just choose one. But, since your rep is low. :) – Sean Vaughn Sep 25 '12 at 14:20
1

let's try:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            int i = 0;
            using (var obj = new TestObj())
            {
                if (i == 0) goto Label;
            }
            Console.WriteLine("some code here");

        Label:
            Console.WriteLine("after label");

        Console.Read();
        }
    }

    class TestObj : IDisposable
    {
        public void Dispose()
        {
            Console.WriteLine("disposed");
        }
    }

}

Console output is : disposed after label

Dispose() execute before codes after the label .

yukaizhao
  • 681
  • 5
  • 17
1
using(Stream s = new Stream("blah blah blah"))
{    
    if(someCondition) goto myLabel;
}

equals to

Stream s;
try
{
     s = new Stream("blah blah blah");
     if(someCondition) goto myLabel;
}
finally
{
  if (s != null)
    ((IDisposable)s).Dispose();
}

So, as soon as you leave the using block, the finally block does happen, no matter what made it quit.

horgh
  • 17,918
  • 22
  • 68
  • 123