Static Readonly fields scoped to methods

Topics: C# Language Design
Jul 17, 2014 at 12:03 PM
We often find ourselves creating private static readonly variables because we want, for example, an array that can be accessed internally to the class to be instantiated one time for the lifetime of the assembly. This makes sense if the static readonly field is accessed by more methods than a single method.
public class Foo
{
    private static readonly string[] SomeCodes = { "Bar", "Baz" };

    public bool ContainsCode(string input)
    {
        return SomeCodes.Contains(input);
    }

    public string FlattenCodes()
    {
        return String.Join(SomeCodes, ",");
    }
}
However, there are time when you only need the static readonly field to be accessed by a single method. The following two methods show the different ways we create arrays for a method, the first being a static readonly array so that it is instantiated and stored a single time (more efficient). The second way, is minutely slower because it is recreating the array, but is more encapsulated (perhaps the array only makes sense to that one implementation of the method):
public class Foo
{
    private static readonly string[] SomeCodes = { "Bar", "Baz" };

    public string CalculateValue(MyObj obj)
    {
        if (SomeCodes.Contains(obj.Code))
            return "X";

        return "Y";
    }

    public string CalculateValueAlt(MyObj obj)
    {
        var codes = new string[] { "Bar", "Baz" };

        if (codes.Contains(obj.Code))
            return "X";

        return "Y";
    }
}
What would be nice is if the compiler could automatically resolve locally scoped static readonly variables and hoist them up to the class level as private static readonly fields. Here is an example of how it could possibly look:
public class Foo
{
    public string CalculateValue(MyObj obj)
    {
        static readonly string[] codes = new string[] { "Bar", "Baz" };

        if (codes.Contains(obj.Code))
            return "X";

        return "Y";
    }
}

// The compiler generates IL as if this were the code to begin with
public class Foo
{
    private static readonly string[] __someAutoGeneratedVariable = new string[] { "Bar", "Baz" };

    public string CalculateValue(MyObj obj)
    {
        string[] codes = __someAutoGeneratedVariable;

        if (codes.Contains(obj.Code))
            return "X";

        return "Y";
    }
}
The hoisted version runs practically at the same rate as the older version since it is only doing an additional reference copy, but a big advantage is that the hoisted version's array is scoped only to the member.
Jul 19, 2014 at 2:30 AM
Any change that reduces the scope to the smallest space possible is better. Old VB6 offered this and it makes determining how code works easier to understand. If you can get the C# team to implement this; they should also build a re-factoring tool to reduce the scope of member variables to the method they are used in if possible. Good luck with this; You have my vote.
Jul 19, 2014 at 4:47 PM
One concern I have with such features is that such variables can make it difficult to capture or restore the state of a class object. Perhaps that issue could be avoided by having a declaration of a static variable foo within method bar be syntactic sugar for the creation of a variable bar_foo, or at least provide a means of specifying that such a variable should be exposed to the enclosing class. That would ensure that if necessary, for testing, serialization, or other such purposes, it would be possible to access such variables in other methods of the class without having to refactor, even if two class methods happened to choose the same name for their internal variables [without such a naming convention, it would be necessary for at least one of the classes to have its variable renamed before it was hoisted to an outer scope].

Incidentally, on a more general note, I believe that things like auto-implemented properties and events, explicit interface implementations, etc. should generally follow such a principle. If a method of a class wants to pass one of its own properties as a ref or out parameter, there should be a way of having it do so without losing the benefit of auto-property syntax. Likewise, if an inheritable class wants to explicitly implement an interface while properly supporting inheritance, it should be able to say
protected void ISomething.SomeMethod(whatever) {...}
which would be equivalent to the VB.NET declaration
Protected Sub ISomething_SomeMethod(whatever) Implements ISomething.SomeMethod
rather than having to write:
void ISomething.SomeMethod(whatever)
{ ISomething_SomeMethod(whatever); }

protected void ISomething_SomeMethod(whatever) {...}
I'm not sure what exactly is gained by having the language use "unpronounceable" names for the backing fields or delegates, given that the whole purpose of the language is supposed to be to serve the programmer, not the other way around.
Jul 19, 2014 at 11:44 PM
Edited Jul 19, 2014 at 11:56 PM
Supercat:
One concern I have with such features is that such variables can make it difficult to capture or restore the state of a class object. Perhaps that issue could be avoided by having a declaration of a static variable foo within method bar be syntactic sugar for the creation of a variable bar_foo, or at least provide a means of specifying that such a variable should be exposed to the enclosing class. That would ensure that if necessary, for testing, serialization, or other such purposes, it would be possible to access such variables in other methods of the class without having to refactor, even if two class methods happened to choose the same name for their internal variables [without such a naming convention, it would be necessary for at least one of the classes to have its variable renamed before it was hoisted to an outer scope].
My suggested expansion of the syntactic sugar was following how automatic properties are expanded. There is a backing field, but it the name is generated and does not follow any naming convention that I'm aware of. I don't agree that the backing field being hoisted up should be based on a naming convention since it should never be accessed outside of the originally intended variable within the member.

Another issue with using a naming convention is overloaded operators, what should be the naming convention if I have the following? We can't simply hoist up the variable and create a private backing field named foo_codes because it would collide. It's best to have the backing field be generated and inaccessible outside of someone being sneaky and reflecting into the class.
public void Foo()
{
    var codes = new string[] { "Bar", "Baz" };
}

public void Foo(int input)
{
    var codes = new string[] { "Bar", "Baz" };
}
Also, as a side note, a friend of mine mentioned that this can also apply to non-static members all the same, so long as the local variable is marked with the readonly keyword.
Jul 20, 2014 at 3:09 AM
Edited Jul 20, 2014 at 3:09 AM
Similar functionality is available in VB, and I've never really understood why it was not supported by C#.
Normally, a local variable in a procedure ceases to exist as soon as the procedure stops. A static variable continues to exist and retains its most recent value. The next time your code calls the procedure, the variable is not reinitialized, and it still holds the latest value that you assigned to it. A static variable continues to exist for the lifetime of the class or module that it is defined in.
http://msdn.microsoft.com/en-us/library/z2cty7t8.aspx
Jul 21, 2014 at 6:34 PM
myermian wrote:
My suggested expansion of the syntactic sugar was following how automatic properties are expanded. There is a backing field, but it the name is generated and does not follow any naming convention that I'm aware of. I don't agree that the backing field being hoisted up should be based on a naming convention since it should never be accessed outside of the originally intended variable within the member.
If the default is for members to have unpronounceable names, that's fine, but if a method uses a local static with a particular name and it becomes necessary for outside code to access that variable (whether for serialization, diagnostics, or whatever) it should be possible for it to do so without having to change the name that's used within the method nor expose into the enclosing class a name that might conflict with other names.
Another issue with using a naming convention is overloaded operators, what should be the naming convention if I have the following? We can't simply hoist up the variable and create a private backing field named foo_codes because it would collide. It's best to have the backing field be generated and inaccessible outside of someone being sneaky and reflecting into the class.
I can't think of any case where it would be appropriate for like-named functions to have distinct static variables with the same name. I would suggest that in deciding whether a language feature is good, one should consider asking people who know C#, "Supposing C# were extended to allow the following code. What would you expect it to mean, and how certain would you be about that". If I were shown code which used the same static variable within two overloads of the same named method, I would expect that they probably referred to different variables, but I wouldn't be certain, since in all cases I can think of it would be more useful to have the functions all access the same variable. Given that it's unclear what such code should mean if like-named static variables are declared in overloads of like-named functions, I would favor requiring that like-named functions have distinct names for their variables, and thus wouldn't consider it a problem.

Still, while I think C# would have been a better language if it used defined names for compiler-generated fields, I'm thinking a better approach to fill this need might be something like:
void myMethod()
{
  instance static int foo=23; // Creates an "obscure-name" instance member, only accessible within method
  static int bar=45; // Creates an "obscure-name" static member, only accessible within method
  ..
}
to be rewritten as either
void myMethod()
{
  export int foo (as private myMethod_foo) =23;
  export static int bar (as private static myMethod_bar) =45;
}
or--using a feature requested elsewhere
private int myMethod_foo = 23;
private static myMethod_bar = 45;
void myMethod() using foo=myMethod_foo, bar=myMethod_bar;
{
  ..
}
Having a method-scoped ability to define aliases would be useful for reducing verbosity in many cases, and in situations like this would help minimize the number of lines changed by refactoring, and avoid any potential problems that would occur if, after variable name within the code were changed to myMethod_foo, an earlier change--from a time where the variable was called foo--got rolled back. If the only thing that changes about the variable is its accessiblity, only lines related to the variables accessibility should need to change--an objective which is met with either of the last two forms.
Also, as a side note, a friend of mine mentioned that this can also apply to non-static members all the same, so long as the local variable is marked with the readonly keyword.
I don't think readonly should matter, since it wouldn't be inherently obvious whether the intention would be to have one mutable array shared among all class instances, or have each instance include its own mutable array. Actually, the more I think about it, the more I think the right approach would be to restrict exporting to instance members, and support method-local using aliases as shown above. Otherwise, given:
    static readonly string[] codes = new string[] { methodReturningString() };
when should methodReturningString() get called?
Jul 25, 2014 at 3:45 PM
supercat wrote:
myermian wrote:
My suggested expansion of the syntactic sugar was following how automatic properties are expanded. There is a backing field, but it the name is generated and does not follow any naming convention that I'm aware of. I don't agree that the backing field being hoisted up should be based on a naming convention since it should never be accessed outside of the originally intended variable within the member.
If the default is for members to have unpronounceable names, that's fine, but if a method uses a local static with a particular name and it becomes necessary for outside code to access that variable (whether for serialization, diagnostics, or whatever) it should be possible for it to do so without having to change the name that's used within the method nor expose into the enclosing class a name that might conflict with other names.
That's a good point (in terms of serialization and diagnostics). The main request was to get some sort of "hoisting" ability, which should really just be syntactic sugar; basically, allow the static and/or readonly keywords to be applicable to local member variables similar to how the const keyword is available. So, when it comes to the private backing field's member name, it isn't as much of a concern, so long as it isn't accessible without doing some sneaky reflection just as you would have to do to gain access to the private backing field when you use automatic properties.

supercat wrote:
myermian wrote:
Another issue with using a naming convention is overloaded operators, what should be the naming convention if I have the following? We can't simply hoist up the variable and create a private backing field named foo_codes because it would collide. It's best to have the backing field be generated and inaccessible outside of someone being sneaky and reflecting into the class.
I can't think of any case where it would be appropriate for like-named functions to have distinct static variables with the same name. I would suggest that in deciding whether a language feature is good, one should consider asking people who know C#, "Supposing C# were extended to allow the following code. What would you expect it to mean, and how certain would you be about that". If I were shown code which used the same static variable within two overloads of the same named method, I would expect that they probably referred to different variables, but I wouldn't be certain, since in all cases I can think of it would be more useful to have the functions all access the same variable. Given that it's unclear what such code should mean if like-named static variables are declared in overloads of like-named functions, I would favor requiring that like-named functions have distinct names for their variables, and thus wouldn't consider it a problem.
It could go either way here. It makes equally as much sense to create a private backing field for each overloaded method as it does if common variable names of common method names were shared; I would consider both of us to be very familiar with C#, and each of us thought of the hoisted variable in a different way. I do think that it is less confusing if the private backing fields are not shared. Imagine the scenario where someone is upgrading their code, whereas it previously looked as so:
public void Foo()
{
    var codes = new[] { "Bar", "Baz" };

    // etc...
}

public void Foo(int option)
{
    var codes = new[] { "Baz" };

    // etc...
}
Understandably, this could be an argument of bad design, but at the end of the day the code compiles in such a way that both methods create a local variable to be used only within the method, and both are expecting that their version of codes is exactly as they expect. In this scenario, marking codes as a static readonly would help gain efficiency with no negative impact to the actual logic provided the compiler creates a private backing field for each local variable independently of the other.

supercat wrote:
myermian wrote:
Also, as a side note, a friend of mine mentioned that this can also apply to non-static members all the same, so long as the local variable is marked with the readonly keyword.
I don't think readonly should matter, since it wouldn't be inherently obvious whether the intention would be to have one mutable array shared among all class instances, or have each instance include its own mutable array. Actually, the more I think about it, the more I think the right approach would be to restrict exporting to instance members, and support method-local using aliases as shown above. Otherwise, given:
static readonly string[] codes = new string[] { methodReturningString() };
when should methodReturningString() get called?
Well, if this is just syntactic sugar, the local variable would just be hoisted up, so it would follow the same rules as if the code was written as follows:
public class FooBar
{
    private static readonly string[] _codes = new string[] { methodReturningString() };

    public void Foo()
    {
        var codes = _codes;

        // etc..
    }
}
Which, obviously would require that methodReturningString() to be a static method. This makes sense because the question/example was marking the local variable as static readonly.

As far as implementing this using other requested features (i.e. "Having a method-scoped ability to define aliases would be useful for reducing verbosity in many cases"), I personally side with using pre-existing keywords and/or syntax. Of course, no new feature request is truly pre-existing, but in this case, we already have an example of how the const keyword can be applied to a local variable, so it isn't too difficult to extend that to the static and/or readonly keywords, compared to rolling out method-scoped aliases; it would be easier to get something in vNext if the feature request did not rely on the addition of a different feature request. And, additionally, and of course this is just my opinion, it looks a lot cleaner to me than to see using aliases on methods.
Jul 26, 2014 at 12:50 AM
I do think that it is less confusing if the private backing fields are not shared.
My preference would be to forbid entirely cases where fields with the same name are used in different overloads of like-named functions. A major point that I think you miss is that initializations such as the ones you've shown create mutable arrays. It would be nice if .NET had included both mutable and immutable array types, but it didn't. If each methods sets codes how it wants it, and neither method modifies its own codes array, non-aliased behavior would be fine. The problem, though, is that there's no way to prevent an array from being passed to code that will modify it.

As for the timing of initialization, I would find it "surprising" if the existence of code:
void foo(int x)
{
  if (x > 0)
  {
    readonly static int[] arr = methodWithSideEffectsReturningArray();
  }
}
caused methodWithSideEffectsReturningArray() to get spontaneously called even if x was never greater than zero. If the array is only useful within that scope, limiting its scope would be conceptually just as justifiable as having it anywhere else within the method.
Jul 26, 2014 at 3:32 AM
Edited Jul 26, 2014 at 3:33 AM
supercat wrote:
A major point that I think you miss is that initializations such as the ones you've shown create mutable arrays. It would be nice if .NET had included both mutable and immutable array types, but it didn't. If each methods sets codes how it wants it, and neither method modifies its own codes array, non-aliased behavior would be fine. The problem, though, is that there's no way to prevent an array from being passed to code that will modify it.
Well, I'm not sure how my suggestion would create a mutable array. I guess it would depend on what exactly you define to be mutable. The reference itself would immutable, but yes, the values in the indexes could be altered and the values themselves are not immutable, but, again, that isn't any different if you simply created a local variable the same way.

You definitely bring up a good point about the timing of the initialization. If the local variable is hoisted up as a private static readonly backing field it could definitely cause unintended side effects, especially in your sample. I'm not sure about the overhead, but perhaps a solution to that would be to use Lazy<T>:
public class Foo
{
    private static readonly Lazy<string[]> __backing = new Lazy<string[]>(() => methodWithSideEffectsReturningArray());

    public void Bar(int x)
    {
        if (x > 0)
        {
            var arr = __backing.Value;
        }
    }
}
Of course, this means that, similar to async/await, the developer would have to consider the overhead to determine whether or not to utilize the feature, and in some situations it might not be worth it (i.e. the local variable initialization results in very few instructions and/or the method is being called too few times).

Additionally, some other food for thought is this:
  • A developer might not intend for the local variable to be static readonly, so they'd have to have a good understanding of hoisting; they might want the methodWithSideEffectsReturningArray() method to be called on each call of foo because they want the side effects to be executed each time. This scenario would mean that the developer should not mark the local as static readonly, but simply a local variable recreated each time so that the side effects execute each time.
  • I'm not sure how well this would play out in terms of multi threading? But, is this a scenario that has to be accounted, or is it on the developer to handle this situation. I guess, does Microsoft worry about multithreading issues when expanding out the foreach, using, yield, etc. keywords?
  • Are there any other scenarios this would cause issues when mixing in with other keywords? That is, would the foreach, using, yield, async/await code/state machines have to be readjusted to account for this feature, or would they work together well?
  • Would this feature interfere with other new features (null propagation, primary constructors, etc.)?
  • If Lazy<T> is used, would that cause any serialization or diagnostic issues?
Also, I still don't think that the hoisted variables should have any possibility of being shared, even in situations of similar names in similarly named (overloaded) methods. But, I guess that's where the benefit of the community could come in -- we had a similar issue of which way to go with null propagation -- basically, the community would need to decide what makes more sense, shared or non-shared private backing fields.
Jul 27, 2014 at 3:59 PM
myermian wrote:
Well, I'm not sure how my suggestion would create a mutable array. I guess it would depend on what exactly you define to be mutable. The reference itself would immutable, but yes, the values in the indexes could be altered and the values themselves are not immutable, but, again, that isn't any different if you simply created a local variable the same way.
Your declaration creates an array. All arrays types in .NET are mutable. Thus your declaration creates a mutable array.

I really wish .NET had included immutable array types and provided a means by which classes could specify that they are immutable (a generic type like ImmutableList<T> would promise to always contain the same T's; T is a reference type, the list would promise to always identify the same objects, but could make no promise about whether those objects might be immutable). If it did so, I would like the idea of allowing static immutable objects to be declared within a method. Unfortunately, the only class type a compiler can count on to be immutable is String.
You definitely bring up a good point about the timing of the initialization. If the local variable is hoisted up as a private static readonly backing field it could definitely cause unintended side effects, especially in your sample. I'm not sure about the overhead, but perhaps a solution to that would be to use Lazy<T>:
Code which wants late initialization could certainly implement that explicitly. My concern is that it if a static variable within a method is initialized with a method which has side effects or--more likely--might rely upon other actions having already been performed, it would be unclear whether the programmer intended that the variable be initialized early, intended that it be initialized late, or was intending to have it not matter.

I would like to see a mechanism by which things which are initialized at class scope could specify early, late, or "whenever" intialization--both for static and instance members. If that feature existed and intra-method static declarations were tagged with such indications, I might consider that a solution to the "timing" question.
  • A developer might not intend for the local variable to be static readonly, so they'd have to have a good understanding of hoisting; they might want the methodWithSideEffectsReturningArray() method to be called on each call of foo because they want the side effects to be executed each time. This scenario would mean that the developer should not mark the local as static readonly, but simply a local variable recreated each time so that the side effects execute each time.
Certainly if that was the developer's intention, the variable shouldn't be static. My point was that if someone is reading a piece of code and sees a static variable that appears to be initialized within a conditional branch, it would look as though the variable would likely be initialized each time that code executes.
  • I'm not sure how well this would play out in terms of multi threading? But, is this a scenario that has to be accounted, or is it on the developer to handle this situation. I guess, does Microsoft worry about multithreading issues when expanding out the foreach, using, yield, etc. keywords?
Syntactical sugar should generally be threading-agnostic. The only syntax sugar I'm aware of that presently isn't, aside from the obvious async support, is the implementation of iterators. I'm not sure what profiling was done to suggest that it would be beneficial for an iterator to return itself as its first enumerator in single-threaded scenarios (while including code to ensure that multi-threaded use would always return new enumerators).
Also, I still don't think that the hoisted variables should have any possibility of being shared, even in situations of similar names in similarly named (overloaded) methods. But, I guess that's where the benefit of the community could come in -- we had a similar issue of which way to go with null propagation -- basically, the community would need to decide what makes more sense, shared or non-shared private backing fields.
I don't think fields should be inherently shared. My point was that I would favor requiring that the compiler should disallow situations where it would appear that they might be. Further, in the event that it becomes necessary for such a variable to be used somewhere other than the point of declaration, there should be a means by which that can be accomplished without having to modify all of the original places where the variable was used.

Suppose, for example, after a method is written it becomes necessary to add an overload which borrows much of the same code but needs to remain as a distinct method [e.g. because it uses different a different pattern of lock or try/catch blocks]. If the original method looked like:
void method(int)
{
  ...
  static theStatic...;
  ...
}
then when the new method was added, the code would become either:
static method_theStatic;
void method(int foo) 
  using theStatic=method_theStatic
{
  ...
}
void method(int foo, Object theLock) 
  using theStatic=method_theStatic
{
  ...
}
or
static method_int_theStatic;
void method(int foo) 
  using theStatic=method_int_theStatic
{
  ...
}
static method_int_Object_theStatic;
void method(int foo, Object theLock) 
  using theStatic=method_int_Object_theStatic
{
  ...
}
In the former case, both overloads would use the same variable, and in the latter case they would use different variables; no change to the interior of theMethod would be required in either case, however, and--most important--anyone who looked at either program would be able to very easily tell whether the two methods were supposed to use the same variable.
Aug 11, 2014 at 2:53 PM
supercat wrote:
myermian wrote:
Well, I'm not sure how my suggestion would create a mutable array. I guess it would depend on what exactly you define to be mutable. The reference itself would immutable, but yes, the values in the indexes could be altered and the values themselves are not immutable, but, again, that isn't any different if you simply created a local variable the same way.
Your declaration creates an array. All arrays types in .NET are mutable. Thus your declaration creates a mutable array.

I really wish .NET had included immutable array types and provided a means by which classes could specify that they are immutable (a generic type like ImmutableList<T> would promise to always contain the same T's; T is a reference type, the list would promise to always identify the same objects, but could make no promise about whether those objects might be immutable). If it did so, I would like the idea of allowing static immutable objects to be declared within a method. Unfortunately, the only class type a compiler can count on to be immutable is String.
Microsoft does have Immutable Collections (http://msdn.microsoft.com/en-us/library/dn385366(v=vs.110).aspx), but that is outside of the scope of this suggestion. The suggestion truly falls back to hoisting up a local variable as syntactic sugar. If someone truly wants to have an immutable collection as a local variable then they should create one within the method. The syntactic sugar should not attempt to expand a standard array into an immutable collection if the developer does not specify that by doing static readonly ImmutableCollection local = ...
supercat wrote:
myermian wrote:
You definitely bring up a good point about the timing of the initialization. If the local variable is hoisted up as a private static readonly backing field it could definitely cause unintended side effects, especially in your sample. I'm not sure about the overhead, but perhaps a solution to that would be to use Lazy<T>:
Code which wants late initialization could certainly implement that explicitly. My concern is that it if a static variable within a method is initialized with a method which has side effects or--more likely--might rely upon other actions having already been performed, it would be unclear whether the programmer intended that the variable be initialized early, intended that it be initialized late, or was intending to have it not matter.

I would like to see a mechanism by which things which are initialized at class scope could specify early, late, or "whenever" intialization--both for static and instance members. If that feature existed and intra-method static declarations were tagged with such indications, I might consider that a solution to the "timing" question.
I thought about this some more, and Lazy<T> should definitely be the way to go. At the end, no matter how "hoisting" is done, if it is truly going to be syntactic sugar, then the expanded code must be consistent. I think that the final code should always look as follows (before/after):

Before:
public void Method()
{
    static readonly T local = hoisted_value;

    ...
}
After:
private static readonly Lazy<T> _hoisted = new Lazy<T>(() => hoisted_value);

public void Method()
{
    T local = _hoisted.Value;

    ...
}
Of course, the static keyword is optional, as long as it is marked as readonly. Also, T can be of any type. The key part here is that if the hoisted value is lazily evaluated, we do not have to worry about any situation where side-effect methods can be triggered during class initialization or instantiation. Here are some examples that cover all bases:

Before:
// Yes, you can hoist up a Lazy<T> as well (it turns into a lazily loaded Lazy<T>).
public void Method()
{
    static readonly Lazy<int> local = new Lazy<int>(() => 5);

    ...
}
After:
private static readonly Lazy<Lazy<int>> _hoisted = new Lazy<Lazy<int>>(() => new Lazy<int>(() => 5));

public void Method()
{
    Lazy<int> local = _hoisted.Value;

    ...
}
Before:
// Just an instance member, not static across all instances.
public void Method(bool switch)
{
    if (switch)
    {
        readonly string[] local = someMethodWithSideEffects();
    }

    ...
}
After:
private readonly Lazy<string[]> _hoisted = new Lazy<string[]>(() => someMethodWithSideEffects());

public void Method()
{
    if (switch)
    {
        string[] local = _hoisted.Value;
    }

    ...
}
The Before section can really be implemented however necessary, whether it is with using directives per method, or simply adding keywords. But, the after (the expanded sugar), should definitely be how it is, with lazy evaluation so that side effects are not caused.

Other notes:
  • I still think that the hoisted private backing field, even if generated by naming convention, should only be accessible to that method (not shared at all).
  • I honestly think that using the static/readonly keywords would be a better syntactic sugar implementation compared to having using directives at the method name, especially given the second scenario (the side effects only occur upon evaluation if the switch is true, which it might never be).