Great developers seek out patterns that prevent errors, unintended behaviors, and promote readability. This post will discuss one of these best practices.
In the Microsoft C# documentation the “if” keyword is documented as part of an “if-else” statement (if-else reference). The else part is important enough to be included in the name of the statement.
if (object.property == SomeEnum.AnEnumValue)
{
// do something
}
When you write an if statement similar to the example above; one of two things is happening:
- You didn’t think about or plan for what should happen if the condition is false
- You did think about it; and you understand the code base well enough to know it’s not an issue
The if SHOULD be followed by an else-statement
if (object.property == SomeEnum.AnEnumValue)
{
// do something
}
else
{
// handle negative logic branch
}
Adding the else-statement here can force you to deal with the fact that every if statement has two outcomes despite whether or not you’ve coded the else-statement. It can also help communicate to other developers on your team that the else-statement side of the branch has no negative impact on the logic or state of the application.
Some developers will argue the code is cleaner, more concise and more readable otherwise, and in most cases I’d probably disagree, of course there are exceptions. A best practice is a guideline not a rule.
If you don’t have anything to code in the else-statement just add a comment, of // intentional empty branch
if (object.property == SomeEnum.AnEnumValue)
{
// do something
}
else
{
// intentional empty branch
}
The reason for this is that it is ALMOST UNIVERSALLY TRUE that if the then-statement side has a DESIRED effect on the state of the application, the else-statement side has an UNDESIRED effect on the state of the application.
if (object.property != SomeEnum.Unknown)
{
// do something, because the property is not set to the Unknown State of the enum
}
else
{
// can't write code for a unidentified use case
// must throw an exception, because there isn't a definition of how to proceed
throw new InvalidOperationException("Object.Property, was set to Unknown");
}
Which could also be written in reverse
if (object.property == SomeEnum.Unknown)
{
// can't write code for a unidentified use case
// must throw an exception, because there isn't a definition of how to proceed
throw new InvalidOperationException("Object.Property, was set to Unknown");
}
else
{
// do something, because the property is not set to the Unknown State of the enum
}
Or even better using a optimistically named and descriptive conditional variable
bool isPropertyValid = object.Property != SomeEnum.Unknown;
if (isPropertyValid)
{
// do something, because the property is not set to the Unknown State of the enum
}
else
{
// can't write code for a unidentified use case
// must throw an exception, because there isn't a definition of how to proceed
throw new InvalidOperationException("Object.Property, was set to Unknown");
}
This practice is so essential because we tend to gravitate towards testing what we expect to happen when writing if-else statements. To ensure that you don’t make costly assumptions, it’s crucial to define what might happen if the condition isn’t true.