Reputation: 7073
I have been looking around finding the best possible option for handling null objects in calling a method (or method chain).
It is our common practice to check with if condition:
if ( customObject != null ) {
customObject.callMe();
}
Which can be further improved by using extension methods:
Program customObject = null;
if (customObject.NotNull()) {
customObject.CallMe();
}
public static bool NotNull(this object o) {
return o == null;
}
PLEASE NOTE: I normally ignore ! from my programming practice. Hence it is wise to say that for me extension methods are good to go.
However, it becomes very complicated in dealing with when the Method chain is involved.
customObject.CallMe().CallMe2() ex...
How you do think it can be handled in C#, so that the CallMe
is called only if customObject
is not null and CallMe2
is called only if CallMe
returns non null object.
Of course I can use If conditions or ternary operator. However, I would want to know if vNext, C#5.0 has some thing to offer.
Upvotes: 7
Views: 10350
Reputation: 4735
In the upcoming C# 6 (vNext) has the ?.
operator (Null Conditional Operator) which easily allow you to chain null reference checks for every nested property.
An example of this would be:
int? first = customers?.[0].Orders?.Count();
This was a requested feature in the Visual Studio UserVoice site
You can see the status for all the new language features for C# 6.0 on the Codeplex site for Roslyn:
Upvotes: 17
Reputation: 365
Since people are tearing apart the answer that assumes you aren't an idiot, here is one that assumes you are.
You should have checked when customObject
was created, because that is the point at which you would have know why you got a null. If you didn't check then, your best bet now is to let your code throw the exception. If there is still something you can do that makes perfect sense without having the object you clearly need, you can fix that up in the catch of the exception, but there probably isn't.
All of the mechanisms that ignore the significance of an unexpected null are just passing along the failure to have paid attention earlier, including habitual overuse of the proposed null-propagation operator, and all habits of checking objects before use. They are seeking an efficient response to a catastrophe that minimizes attention paid to it.
If you are signalling important information with the nullness of an object, that is probably a bad design choice, and you should have converted the null into more usable information when it was introduced.
Testing for the unexpected nullness of an object right before it is used, rather than right after it is produced cannot really help anyone. It is a code-smell that indicates you have misplaced responsibility, probably in one of these ways:
The policy you indicate, of eating the null and continuing execution without analyzing it, is a bad one. If you intend to keep it, that is my other answer. You should instead do something reasonable.
In a lot of workplaces, putting an empty catch block anywhere is a clear documentation of future work. So it is doing something. But leaving it there is never an option that should stand in good code. Such a block would more reasonably convert the exception into a response that creates future work to fix the source of the error, even if the code-block implements a workaround that addresses the problem in a more local way.
Upvotes: 1
Reputation: 365
This is the point of exception handling. If you want to respond to unusual circumstances like getting an unexpected null returned from a function, then catch the NullReferenceException, and call your recovery code from there. The exception itself will stop further calls, so if that is all you wish to accomplish, implement no recovery code. I do not suggest this is a reasonable response, something like this should generally at least be logged.
try
{
customObject.CallMe().CallMe2()
}
catch (NullReferenceException ex)
{
/* save enough details to determine why you got an unexpected null */
}
Do not use exception handling to accomplish normal programming tasks, but do not avoid it excessively, by checking for every possible contingency, no matter how rare. Decide what failures are likely in your code (that you can do anything about) and include a healthy list of catch'es at the end of each reasonable-sized block.
Upvotes: -6
Reputation: 117064
You can currently write these kinds of extension methods:
public static class Extensions
{
public static R IfNotNull<T, R>(this T @this, Func<T, R> @select) where T : class
{
return @this.IfNotNull(@select, () => default(R));
}
public static R IfNotNull<T, R>(this T @this, Func<T, R> @select, Func<R> @default) where T : class
{
return @this != null ? @select(@this) : @default();
}
public static void IfNotNull<T>(this T @this, Action<T> @action) where T : class
{
if (@this != null)
{
@action(@this);
}
}
}
Then call them like so:
customObject
.IfNotNull(y => y.CallMe())
.IfNotNull(y => y.CallMe2());
Upvotes: 4
Reputation: 10432
C# 6 does have the ?
operator, otherwise you can look into monads, particularly the Maybe
monad, e.g. here, here, elsewhere. Is it worth using monads in a non-functional language that wasn't designed with them in mind is a different question.
Upvotes: 0
Reputation: 4744
C# 5 has nothing to offer to simplify your code. You are stuck with either:
However, the future may be brighter, as the null-propagating operator ?. is a proposed feature of C# 6, and has already be implemented is Roslyn, so it would be a great surprise if it was not effectively in C# 6. With this operator, you will be able to write
customObject?.CallMe()?.CallMe2()?.[...]
And the compiler will create the nested if for you (and even ensure that every method is only called once). So, A little more patience...
Upvotes: 2