When do you use scope without a statement in C#?

前端 未结 5 917
情深已故
情深已故 2021-01-17 07:26

Just recently I found out you can do this in C#:

{
    // google
    string url = \"#\";

    if ( value > 5 )
        url = \"http://google.com\";

    m         


        
5条回答
  •  感情败类
    2021-01-17 08:05

    You could use {} to to repurpose variable names (even for different types):

    {
       var foo = new SomeClass();
    }
    {
       Bar foo = new Bar(); // impairs readability
    }
    

    However, repurposing variables in this way will confuse readability.

    So instead of using "unsolicited" scope block without a preceding statement, in most cases the code should instead be refactored into separate functions accordingly.

    Edit

    IMO, any time there is the need to imperatively reset local mutable variable values or repurpose them for additional or alternative concerns is a sign of a smell. e.g. the original code can be refactored as:

    menu.Add( value > 5 
                ? new MenuItem("http://google.com")
                : new MenuItem("#"));
    
    menu.Add( value > 45 
                ? new MenuItem("http://cheese.com")
                : new MenuItem("#"));
    

    Which I believe conveys the intention, without the risk of the # fallback not being applied, and without the need for explicit local mutable variables to hold state.

    (or new MenuItem(value > 45 ? "http://cheese.com" : "#"), or create an overload of MenuItem with a default of #, or move the creation of MenuItem into a factory method, etc.)

    Edit
    Re : Scope has no effect on lifespan

    Scope can be used within a method to limit the lifespan of expensive objects

    My initial post incorrectly stated that local scope could be used to influence the lifespan of objects. This is incorrect, for both DEBUG and RELEASE builds, and irrespective of whether the variable name is reallocated or not, as demonstrated by Jeppe's IL disassembly, and by these Unit tests here. Thanks to Jeppe for pointing this out. In addition, Lasse makes the point that even without explicitly going out of scope, variables no longer in use will be eligible for garbage collection in release builds.

    TL;DR Although use of unsolicited scope may help convey the logical use of a variable scope to a human, doing so has no influence on whether the object becomes eligible for collection, within the same method.

    i.e in the code below, scoping, and even re-purposing the variable foo below has absolutely no effect on lifespan.

    void MyMethod()
    {
      // Gratuituous braces:
      {
          var foo = new ExpensiveClass();
      }
      {
          Bar foo = new Bar(); // Don't repurpose, it impairs readability!
      }
      Thread.Sleep(TimeSpan.FromSeconds(10));
      GC.Collect();
      GC.WaitForPendingFinalizers();
      <-- Point "X"
    }
    

    At Point X:

    • In a DEBUG build, neither of the foo variables will have been collected despite the hacky attempts to entice the GC to do so.
    • In a RELEASE build, both foos would have been eligible for collection as soon as they aren't needed, irrespective of the scope. The timing of collection of course should be left to its own devices.

提交回复
热议问题