This Feature Intentionally Left Blank

A few posts ago I put out a bullet outline of the lengthy agenda for ModVB. I intentionally didn’t do much editing to it since the point was to be more comfortable publishing things before they’re in a final, marketing-approved state, as is the habit I developed over 8 years at Microsoft.

One particularly attentive reader noticed an item I had forgotten I’d left in the outline with a rather curious heading: “10.4 This feature intentionally left blank”. I suspect he thought it was a joke–a eccentric reference to the Intentionally blank pages that sometimes appear in printed books and such. Per Wikipedia, “Such notices typically appear in printed works, such as legal documents, manuals, and exam papers, in which the reader might otherwise suspect that the blank pages are due to a printing error and where missing pages might have serious consequences”.

While it’s definitely a reference to that, it’s not a joke. This is a feature I’ve been mulling over for a couple of years now and I want to walk you through a few scenarios.

More than a decade ago, while making some code change for Roslyn, I think I was either making a class into a singleton or at least making sure it didn’t have a public constructor. VB and C# are both languages which don’t force you to explicitly declare a default constructor. If you don’t define any constructors, a public one is implicitly defined for you with no arguments. That means if you don’t want a public constructor, you must define one so that you can mark it private, even if it has no other functionality. It must exist to not be called. Leading to an odd looking block of code like this:

Private Sub New()
End Sub

I find an End Sub statement immediately after a Sub New() statement to look weird (It’s almost never the case that a statement block exists with no code inside of it so of course it looks weird. So instead I wrote this to look less weird and make it look less weird.

Private Sub New()
    Return
End Sub

Which I found better but in code review someone commented that seeing a constructor immediately return also looked weird, to them. I assume we compromised on a comment like,

Private Sub New()
    ' This is not a mistake. This constructor is supposed to be empty.
End Sub

That’s a fine solution. And if that were the only niche case I wouldn’t be writing this post, but read on.

Sometimes when you inherit a class, operations may include certain default behaviors for convenience which you need to turn off for whatever reason. Liskov Substitution aside and without regard to whether this is a good design for a base class author or not, this is a situation that may pop up. When it does it may be that you need to override some protected method simply to make sure that when a operation occurs, this extra behavior is not executed or an otherwise meaningless or inapplicable command is ignored.

' For 99% of controls either the default (rectangular) size calculation
' is fine, or the logic should be specifically overridden. But, in the
' case of this control, all size calculation is handled by the
' container and no logic should execute nor `Resized` events raised.
Protected Overrides Sub OnArrangeCalled()
    '
End Sub

The pattern illustrated by these examples is default behavior which is usually correct and convenient to provide by default but that in a minority case needs to be turned off. And reviewers and maintainers should be alerted that the conspicuously empty statement block isn’t there because the rest of the code was forgotten, or a file was hastily checked in without saving, but is empty by design. That is to say that it is intended that in that case the program should do nothing.

Introducing the Do Nothing Statement

That’s right. Whenever I’m out in the world reading words and I see the expression “do nothing” I see the two words colored in keyword blue. This is my curse to bear. If VB didn’t already have both of those keywords already I’d have gone on to live a happy and productive life, but here we are.

In true VB fashion this statement does exactly what it says on the tin–nothing. It is, as we say a no-op. And plenty of languages include some kind of no-op instruction, including x86/64 assembly, Python (pass), and .NET IL. And in many C-like languages sometimes the syntax requires a statement so an empty statement–a lone semicolon (;)–must be used. And the compilers emit nop instructions all the time. Have you ever wondered what happens when you set a breakpoint on an End If statement? Block End statements don’t do anything but for debugging purposes the compiler may emit a nop so the debugger can stop at a line which otherwise wouldn’t have corresponding instruction). So the concept of a no-op “statement” already exists in the compiler, it’s just not exposed explicitly in the high-level language.

And in a way this is a statement analog of a null value or a sentinel value like Stream.Null, sometimes you need to have a thing that isn’t a thing at all but fits in a thing-shaped space.

But wait! There’s more!

I wouldn’t blame you for still being skeptical. This has to be the absolute least … existing feature one could ever implement. It doesn’t do anything, doesn’t add new keywords, but doesn’t cost much at all and if it went 6 inches farther in either direction it wouldn’t even be on the line of consideration. In fact this feature is the line of consideration. A feature that does less and/or costs more is certainly not worth discussing. But there are two more scenarios I want to present that have made me warm up to this idea which would otherwise feel simply whimsical. One is stylist and the other is a potential interaction with a possible future feature.

I don’t know why but the longer I grew in the craft I became a little less comfortable with certain kinds of implication. It’s really more a nagging sensation. Or perhaps for simplifying the interpretive simulation in my brain I want to state clearly some things which would otherwise “fall out” later. That is to say I’m less comfortable with asking myself or the reader to do the thought exercise to recognize that a certain thing is the eventual logical consequence of the way I’ve written my code. For example:

Select Case dayOfWeek
    Case DayOfWeek.Monday To DayOfWeek.Thursday
        ...
    Case DayOfWeek.Friday
        ...
    Case DayOfWeek.Saturday
        ...
End Select

Ignoring the limitations of enums (for now), “it goes without saying” that if a day isn’t M-Th, Friday, or Saturday that it must be Sunday. Stylistically, sometimes I want to say things that go without saying. And the more more code interleaved between the cases I’m dealing with and the conclusion that I’m not dealing with Sunday the more bothered I personally get remembering that Sunday wasn’t handled earlier.

It’s a not a correctness thing but a style thing. It depends on the dev, the situation, maybe the day… of the week. I’m not saying what anyone should always do or what I always will do but I think it’s legitimate sometimes to want to expression oneself in that style.

Now there are at least 3 ways to deal with this.

Option 1. Handle Sunday

        ...
    Case DayOfWeek.Sunday
        ...
End Select

Looks clear. But this contends with another feature many developers love, flow analysis. If you’re one who wants the compiler to raise an error if a variable is never assigned on a code path or perhaps a function doesn’t return a value on all code paths, there is a hidden code path here. You and I know that logically there are only 7 days, or 12 months, or that all integers are one of < 0, 0, or > 0, but the compiler doesn’t, especially those first two. So the compiler will flag the invisible code path where it’s a day other than 7 mentioned and complain. So to shut the compiler up it may be tempting to take…

Option 2. Handle the last case with Case Else

        ...
    Case Else
        ...
End Select

This will definitely satisfy the compiler (which is just annoying enough to have to do that one might turn off the warning entirely). But the problem is that this might hide a bug. What should the program do if it is passed an enum value containing -47 (now unignoring the limitations of enums)? Should invalid parameters be treated like Sunday? Maybe. But often, particularly when dealing with enums the programmer not only assumes but would enforce that only valid (defined) enum values are flowing around the program. Values that haven’t been defined may indicate that some other piece of the system isn’t working as expected.

So, on Roslyn in the many places we check for what is believed to be the set of all legitimate cases we handle unexpected cases with…

Option 3. Handle the last defined case explicitly and unexpected cases by throwing

    Case DayOfWeek.Sunday
        ...
    Case Else
        Throw New InvalidOperationException("tf?")
End Select

This satisfies the compiler’s need for completeness, the programmer’s need for correctness, and the reader’s need to know what the writer intended.

You’ll note that none of these 3 options used the proposed Do Nothing statement. This was intentional. I’ve lured you into a trap!

After years of having to add a Case Else to the thousands of enum checks scattered around the codebase “I’m tired, Boss”. And thinking about adding the ability to Select Case on the type of an object and union types this pain will only grow with time.

So I’ve been thinking of ways to eliminate this repetitive boiler plate and at the moment my thinking has landed on a compiler option like Integer Overflow/Underflow Checking or Array Bounds Checking in pre-.NET VB. A flag that let’s you type the code like Option 1 but get the precision and safety of Option 3 by default. The design and merit and alternatives to that flag are beyond the scope of this post but for the sake of argument imagine it was added. Now you can write code in a natural way covering the expected code paths and the compiler will spit out a backstop/assert that throws an exception in the hopefully rare occurrence that somehow execution behaves in an unexpected way (like an integer overflowing, or access outside the bounds of an array, or calling an instance method on a null reference).

This could be a win and it’s basically turning off “implicitly” falling through a Select Case by default. But now what about those cases where you really do want to silently fall through when a value not listed occurs. For example when future proofing; when writing a Roslyn analyzer or other tooling it’s often best to not throw exceptions if you encounter nodes you didn’t expect. If you write a code action for version n of a language that has 2 kinds of parameters ByRef and ByVal and in version n + 1 the language adds a 3rd (e.g. Out) you don’t want your tool to start blowing up because someone updated Visual Studio. Sometimes when you don’t know how to handle a situation, it’s better to… do nothing.

So, if such a safety check flag were added to ModVB, a Do Nothing statement would become more valuable in the cases where “silently” falling through is still desired.

        ...
    Case Else
        Do Nothing
End Select

Which is just a new example of overriding default behavior to turn it off and who knows if more will present themselves.

Many years ago a fun exercise going around the language teams was to figure the simplest syntax in different programming languages for defining and invoking a lambda expression that does nothing. The most unsettling one I recall was this syntax in C++ :

[](){}();

which defines and immediately calls a lambda expression that captures no values, takes no arguments, has no return value, and does nothing.

I like Call (Sub() Do Nothing)() better, honestly!

Wrap up

So, those are the examples that nudged this feature up from “unserious and easily dismissible” to “… there’s an argument to be made for thinking about it seriously”. Did they nudge you? Sound off in the comments!

Regards,

-ADG