Suppose I want to check a bunch of objects to make sure none is null:
if (obj != null &&
obj.Parameters != null &&
obj.Parameters.UserSettings != null) {
// do something with obj.Parameters.UserSettings
}
It is an alluring prospect to write a helper function to accept a variable number of arguments and simplify this kind of check:
static bool NoNulls(params object[] objects) {
for (int i = 0; i < objects.Length; i++)
if (objects[i] == null) return false;
return true;
}
Then the above code could become:
if (NoNulls(obj, obj.Parameters, obj.Parameters.UserSettings)) {
// do something
}
Right? Wrong. If obj
is null, then I'll get a NullReferenceException
when I try to pass obj.Parameters
to NoNulls
.
So the above approach is clearly misguided. But the if
statement using the &&
operator works just fine since it is short-circuited. So: is there any way to make a method short-circuited, so that its arguments are not evaluated until explicitly referenced within the method?
Well, this is ugly but...
static bool NoNulls(params Func<object>[] funcs) {
for (int i = 0; i < funcs.Length; i++)
if (funcs[i]() == null) return false;
return true;
}
Then call it with:
if (NoNulls(() => obj,
() => obj.Parameters,
() => obj.Parameters.UserSettings)) {
// do something
}
Basically you're providing delegates to evaluate the values lazily, rather than the values themselves (as evaluating those values is what causes an exception).
I'm not saying it's nice, but it's there as an option...
EDIT: This actually (and accidentally) gets to the heart of what Dan was after, I think. All a method's arguments are evaluated before the method itself is executed. Using delegates effectively lets you delay that evaluation until the method needs to call the delegate to retrieve the value.
You could write a function that accepts an expression tree and transforms that tree into a form that will check for nulls, and return a Func<bool>
that could be safely evaluated to determine if there is a null.
I suspect that while the resulting code may be cool, it would be confusing, and much less performant than just writing a bunch of short-circuited a != null && a.b != null...
checks. In fact, it would likely be less performant than just checking all the values and catching the NullReferenceException
(not that I advocate for exception handling as a flow of control mechanism).
The signature for such a function would be something like:
public static Func<bool> NoNulls( Expression<Func<object>> expr )
and it's usage would look something like:
NoNulls( () => new { a = obj,
b = obj.Parameters,
c = obj.Parameters.UserSettings } )();
If I get some free time, I will write a function that does just such an expression tree transformation and update my post. However, I'm sure that Jon Skeet or Mark Gravell could write such a function with one eye closed and one hand behind their back.
I would also love to see C# implement the .?
operator that Eric alludes to. As a different Eric (Cartman) might say, that would "kick ass".
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