Just recently I found out you can do this in C#:
{ // google string url = "#"; if ( value > 5 ) url = "http://google.com"; menu.Add( new MenuItem(url) ); } { // cheese string url = "#"; // url has to be redefined again, // so it can't accidently leak into the new menu item if ( value > 45 ) url = "http://cheese.com"; menu.Add( new MenuItem(url) ); }
instead of i.e.:
string url = "#"; // google if ( value > 5 ) url = "http://google.com"; menu.Add( new MenuItem(url) ); // cheese url = "#"; // now I need to remember to reset the url if ( value > 45 ) url = "http://cheese.com"; menu.Add( new MenuItem(url) );
This might be a bad example that can be solved in a lot of other manners.
Are there any patterns where the 'scope without statement' feature is a good practice?
A scope in any programming is a region of the program where a defined variable can have its existence and beyond that variable it cannot be accessed. There are three places where variables can be declared in C programming language − Inside a function or a block which is called local variables.
C has four kinds of scopes: block scope. file scope. function scope.
One of the basic reasons for scoping is to keep variables distinct from each other in multiple parts of the program. For example the programmers can use same variables for all loops such i and j, this can lead collision of variables hence the scope of the variable is necessary to avoid collisions and for more security.
Whenever a scope is introduced, the compiler gives it a name and puts it in a structure (a tree) that makes it easy to determine the position of that scope in relation to other scopes, and it is marked as being the current scope. When a variable is declared, its assigned to the current scope.
One use that I find acceptable in many cases, is to enclose each switch section of a switch
statement in a local scope.
Late addition:
The local scope blocks { ... }
present in the C# source do not seem to be relevant for the resulting IL bytecode. I tried this simple example:
static void A() { { var o = new object(); Console.WriteLine(o); } var p = new object(); Console.WriteLine(p); } static void B() { var o = new object(); Console.WriteLine(o); var p = new object(); Console.WriteLine(p); } static void C() { { var o = new object(); Console.WriteLine(o); } { var o = new object(); Console.WriteLine(o); } }
This was compiled in Release mode (optimizations enabled). The resulting IL according to IL DASM is:
.method private hidebysig static void A() cil managed { // Code size 25 (0x19) .maxstack 1 .locals init ([0] object o, [1] object p) IL_0000: newobj instance void [mscorlib]System.Object::.ctor() IL_0005: stloc.0 IL_0006: ldloc.0 IL_0007: call void [mscorlib]System.Console::WriteLine(object) IL_000c: newobj instance void [mscorlib]System.Object::.ctor() IL_0011: stloc.1 IL_0012: ldloc.1 IL_0013: call void [mscorlib]System.Console::WriteLine(object) IL_0018: ret } // end of method LocalScopeExamples::A
.method private hidebysig static void B() cil managed { // Code size 25 (0x19) .maxstack 1 .locals init ([0] object o, [1] object p) IL_0000: newobj instance void [mscorlib]System.Object::.ctor() IL_0005: stloc.0 IL_0006: ldloc.0 IL_0007: call void [mscorlib]System.Console::WriteLine(object) IL_000c: newobj instance void [mscorlib]System.Object::.ctor() IL_0011: stloc.1 IL_0012: ldloc.1 IL_0013: call void [mscorlib]System.Console::WriteLine(object) IL_0018: ret } // end of method LocalScopeExamples::B
.method private hidebysig static void C() cil managed { // Code size 25 (0x19) .maxstack 1 .locals init ([0] object o, [1] object V_1) IL_0000: newobj instance void [mscorlib]System.Object::.ctor() IL_0005: stloc.0 IL_0006: ldloc.0 IL_0007: call void [mscorlib]System.Console::WriteLine(object) IL_000c: newobj instance void [mscorlib]System.Object::.ctor() IL_0011: stloc.1 IL_0012: ldloc.1 IL_0013: call void [mscorlib]System.Console::WriteLine(object) IL_0018: ret } // end of method LocalScopeExamples::C
Conclusions:
o
in the C
method).I also tried compiling this in Debug mode (no optimizations). The start and end of a local scope seem to show up as a nop
instruction only ("No operation"). In some cases two identically named local variables from distinct local scopes were mapped to the same local variable in the IL, like with C# method named C
above. Such a "unification" of two variables is only possible if their types are compatible.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With