I\'m a bit confused about how to best refactor my code into something more readable.
Consider this piece of code:
var foo = getfoo();
if(foo!=null)
{
Do it old-school:
var foo;
var bar;
var moo;
var cow;
var failed = false;
failed = failed || (foo = getfoo()) == null;
failed = failed || (bar = getbar(foo)) == null;
failed = failed || (moo = getmoo(bar)) == null;
failed = failed || (cow = getcow(moo)) == null;
Much clearer - no arrow - and extendable forever.
Please do not go over to the Dark Side
and use goto
or return
.
var foo = getFoo();
var bar = (foo == null) ? null : getBar(foo);
var moo = (bar == null) ? null : getMoo(bar);
var cow = (moo == null) ? null : getCow(moo);
if (cow != null) {
...
}
This is the one case where I'd use goto.
Your example might not be quite enough to push me over the edge, and multiple returns are better if your method is simple enough. But this pattern can get rather extensive, and you often need some cleanup code at the end. While using most of the other answers here if I can, often the only legible solution is to use goto
's.
(When you do, be sure to put all references to the label inside one block so anyone looking at the code knows both the goto
's and the the variables are confined to that part of the code.)
In Javascript and Java you can do this:
bigIf: {
if (!something) break bigIf;
if (!somethingelse) break bigIf;
if (!otherthing) break bigIf;
// Conditionally do something...
}
// Always do something else...
return;
Javascript and Java have no goto
's, which leads me to believe other people have noticed that in this situation you do need them.
An exception would work for me too, except for the try/catch mess you force on the calling code. Also, C# puts in a stack trace on the throw, which will slow your code way down, particularly if it usually kicks out on the first check.
If you can change the stuff you are calling, you can change it to never ever return null, but a NULL-Object instead.
This would allow you to lose all the ifs completely.
Rex Kerr's answer is indeed very nice.
If you can change the code though,Jens Schauder's answer is probably better (Null Object pattern)
If you can make the example more specific you can probably get even more answers
For example ,depending on the "location" of the methods you can have something like:
namespace ConsoleApplication8
{
using MyLibrary;
using static MyLibrary.MyHelpers;
class Foo { }
class Bar { }
class Moo { }
class Cow { }
internal class Program
{
private static void Main(string[] args)
{
var cow = getfoo()?.getbar()?.getmoo()?.getcow();
}
}
}
namespace MyLibrary
{
using ConsoleApplication8;
static class MyExtensions
{
public static Cow getcow(this Moo moo) => null;
public static Moo getmoo(this Bar bar) => null;
public static Bar getbar(this Foo foo) => null;
}
static class MyHelpers
{
public static Foo getfoo() => null;
}
}
First your suggestion (return after each if clause) is quite a good way out:
// Contract (first check all the input)
var foo = getfoo();
if (Object.ReferenceEquals(null, foo))
return; // <- Or throw exception, put assert etc.
var bar = getbar(foo);
if (Object.ReferenceEquals(null, bar))
return; // <- Or throw exception, put assert etc.
var moo = getmoo(bar);
if (Object.ReferenceEquals(null, moo))
return; // <- Or throw exception, put assert etc.
// Routine: all instances (foo, bar, moo) are correct (not null) and we can work with them
...
The second possibility (in your very case) is to slightly modify your getbar() as well as getmoo() functions such that they return null on null input, so you'll have
var foo = getfoo();
var bar = getbar(foo); // return null if foo is null
var moo = getmoo(bar); // return null if bar is null
if ((foo == null) || (bar == null) || (moo == null))
return; // <- Or throw exception, put assert(s) etc.
// Routine: all instances (foo, bar, moo) are correct (not null)
...
The third possibility is that in complicated cases you can use Null Object Desing Patteren
http://en.wikipedia.org/wiki/Null_Object_pattern