1

Syntax is fine, code runs fine, aside from making it look nicer, what is the point of having curly braces inside of a function?

public void Foo() 
{
    string txt = "hello world";
    { <---- THIS
        Assert.AreEqual("hello world", txt);
    } <---- THIS
}

EXAMPLE: The code was generated using selenium IDE

// Generated by Selenium IDE
  [Test]
  public void fsdafdsafds() {
    driver.Navigate().GoToUrl("https://www.seleniumeasy.com/test/basic-select-dropdown-demo.html");
    driver.Manage().Window.Size = new System.Drawing.Size(1696, 1026);
    driver.FindElement(By.Id("select-demo")).Click();
    {
      var dropdown = driver.FindElement(By.Id("select-demo"));
      dropdown.FindElement(By.XPath("//option[. = 'Sunday']")).Click();
    }
    driver.FindElement(By.Id("select-demo")).Click();
    {
      var dropdown = driver.FindElement(By.Id("multi-select"));
      dropdown.FindElement(By.XPath("//option[. = 'California']")).Click();
    }
    {
      var dropdown = driver.FindElement(By.Id("multi-select"));
      dropdown.FindElement(By.XPath("//option[. = 'New Jersey']")).Click();
    }
    driver.FindElement(By.Id("printMe")).Click();
    driver.FindElement(By.Id("printAll")).Click();
  }
  • 5
    In this case, there is no point. I'd read [Scope and Visibility](https://learn.microsoft.com/en-us/cpp/c-language/scope-and-visibility) for information. – Wai Ha Lee Feb 11 '20 at 16:39
  • 1
    In this particular case, nothing. The braces introduce a scope but that scope is not used here, so nothing happens. –  Feb 11 '20 at 16:39
  • 1
    @Observer - why do you not think the test would pass? – Wai Ha Lee Feb 11 '20 at 16:39
  • 2
    check this link [link](https://stackoverflow.com/questions/7246755/floating-curly-braces-in-c-sharp) – Krishna Varma Feb 11 '20 at 16:40
  • 1
    @Observer The braces don't do anything at all, and will have zero impact on the test. –  Feb 11 '20 at 16:41
  • They might become usefull if one want to insert a condition. – TaW Feb 11 '20 at 16:42
  • @WaiHaLee i've just never seen curly braces thrown in without a reason. I thought the compiler might take issue with it. But as Amy pointed out, it is forgiving :) – Observer Feb 11 '20 at 16:42
  • 1
    @Observer I never said it was forgiving. It said it had no effect. This is perfectly valid. You can use braces as you like within a function to define new variable scopes. There is no "forgiveness" involved here. –  Feb 11 '20 at 16:44
  • The test does pass. Which made me wonder about why someone would put them in there if the syntax doesn't mind it, perhaps there is a reason to it. – Andrew Mills Feb 11 '20 at 16:45
  • 2
    @AndrewMills It might simply be a contrived example, based on their real-world code. We ask people to make [mre], and maybe the OP did. –  Feb 11 '20 at 16:46
  • Updated with the example i found – Andrew Mills Feb 11 '20 at 16:48
  • @AndrewMills Yes, the updated code makes use of the extra variable scopes. –  Feb 11 '20 at 16:52
  • 2
    The reason for the scope is to allow the code generator to "paste in" the same code over and over again and not cause an error for redefining the same variables over and over again. Within each scope, "var dropdown" is defined from scratch. "dropdown" is the variable that would cause the error if all the braces were removed. If you remove all the braces, you will see what I mean. – MicroservicesOnDDD Feb 11 '20 at 16:58
  • And now that more information has been added to this question, it should be reopened, because it is no longer a duplicate! There should be a minimum delay before questions should be closable. – MicroservicesOnDDD Feb 11 '20 at 17:00
  • 2
    that is an excellent way to put it. i have a similiar issue where i keep going button1, button2, button3. now if i scope them i can just go button! Thank you – Andrew Mills Feb 11 '20 at 17:04
  • 1
    @MicroservicesOnDDD No, it's still certainly a duplicate of the indicated question. Nothing has changed. –  Feb 11 '20 at 17:51
  • @AndrewMills Reusing variable names like that in actual hand-written code is a very bad idea that should be avoided. –  Feb 11 '20 at 17:52
  • @Amy -- I consider the generation of the code in the second half to make this question unique compared to the other named as a duplicate. And other seem to agree with me, because this question has been reopened. – MicroservicesOnDDD Feb 11 '20 at 22:12
  • @MicroservicesOnDDD Yes I see that. I disagree with the reopening but am not really interested. –  Feb 11 '20 at 22:15

2 Answers2

2

The curly braces just limit scope. There is plenty of reading material that is pretty easy to find on the topic of "scope," but simply put:

Anything defined within the curly braces has its scope limited to those curly braces, meaning it can not be used outside of the curly braces as it will be destroyed upon going out of scope. There are a few reasons to do something like this.

The first case is shown in your example. var dropdown can be redefined in each scope thus in the first set up curly braces dropdown.FindElement() is operating on the "select-demo" element. In the second set of curly braces, you reuse the same name, "dropdown," to instantiate a new dropdown object, since the old dropdown object has gone out of scope and has been destroyed. This time, dropdown.FindElement() operates on "multi-select." In thisi example, limiting the scope this way is not strictly necessary. You could just overwrite var dropdown.

The second case involves triggering objects with a special destructor. Consider the following pseudo code.

public class Timer
{
    int mStart;

    public Timer()
    {
        mStart = Now();
    }

    ~Timer()
    {
        Console.WriteLine("Elapsed Time: {0}", Now() - mStart);
    }
}

public class MainFunction
{
    public static int Main()
    {
        {
            Timer timer();
            DoSomethingWorthTimming();
        } // <-- ~Timer() is called
        {
            Timer timer();
            DoSomethingElseWorthTimming();
        } // <-- ~Timer() is called
    }

Using scope this way allows you to control when a destructor is called for an object. In this case, that allows us to time a block of code.

Hopefully that helps.

LLSv2.0
  • 501
  • 6
  • 20
1

When generating code, it can be useful to use the curly braces as a scope-limited section of code that can be inserted multiple times in the same method and not have its local variables run into other "instances" of the generated code that appear in the same scope. Also useful is the fact that the code stands out from the other code, and you can see it as a "block" like a software LEGO being assembled mass-production-wise into place. A further benefit would be that search-and-replace would be able to work on all occurrences of that code, but are you re-generating the code repeatedly (then it is dangerous to touch it, and it's off-limits). But if you generated the code once and have to maintain it from there, the search-and-replaceability is a God-send!

But we should not answer this question without pointing out that all of these copies of code just "feels wrong". The DRY -- Don't Repeat Yourself -- rule is obviously being violated. So, for hand-written code, we should probably not do this. But it does point to probably a higher-quality paradigm that could be used instead, which is to use one of the homoiconic languages like LISP, Scheme, Forth, and Factor, which also have no real syntax or keyword limitations, and therefore allow you to write in DSL and do your own metaprogramming and paradigm-creation instead of code-generation. The book that blew my mind away was "Let over Lambda" by Doug Hoyte, and even though most of it is on the web, I bought a copy for the final chapters on optimization and his implementation of Forth in Lisp (wow!) and it was worth it.