'Null-Safe' Dot notation in VB.NET ... or does it exist in any language? 'safe dereferencing operator' or equivalent using LINQ?
I'm looking for a 'safe' dot notation in VB.net. Does such a thing exist - in VB.NET or any language? What I want to be able to do is, when using non-nullable legacy objects, to solve a problem like:
"if there as a plan, if there is a开发者_开发技巧 case, if it has a person, that person's spouse, else, nothing (VBSpeak for Null)."
and avoid doing this:
Dim Spouse as Person = Nothing
if Case.Plan isnot nothing then
if Case.Plan.Person isnot Nothing
Spouse = Case.Plan.Person.Spouse
end if
end if
and do this:
Dim Spouse as Person = Case~Plan~Person~Spouse
Where '~'
is my sought 'safe' dot notation, which immeditely returns a null upon encountering the first null object instead of throwing an exception?
More common for this problem of course:
dim MyVar as string = XMLDoc.DocumentElement.SelectSingleNode("Name").InnerText
and wanting Nothing instead of an exception when Name doesn't exist.
Edit:
Is there a way to solve this problem using LINQ for objects or LINQ for XML?
VB.NET 14 introduced the null-conditional operator to address this. This operator is also short-circuiting.
Dim Spouse as Person = Case?.Plan?.Person?.Spouse
Used to test for null before performing a member access (?.) or index (?[) operation. These operators help you write less code to handle null checks, especially for descending into data structures.
The same thing works in C#:
Person spouse = Case?.Plan?.Person?.Spouse;
I've generally used extension methods for this sort of thing, very similar to what the thread that AakashM pointed to. A good example of this is string LENGTH. Since the LENGTH function is an instance method, if you invoke it on a null string object, you'll throw.
But code up an extension method LEN on the string class that tests for null and you can have it return 0 (I happen to consider null strings 0 length virtually all the time, but that's a topic for another thread.)
Using that same logic, you could implement an IsNotNull, or maybe an IsValid. the main problem will be "stopping" the continued property resolution (from, say, Case to Plan)
the methods on the above mentioned thread use Lambdas, which yields a pretty unwieldy syntax if you ask me. I suspect it'd be possible to, if the IsNotNull test yields a null, to return a Proxy object that stands in for the null, and would simply resolve anything method call you make on it to a null as well. But that would require a dynamic proxy which is messy in and of itself.
That's about it for the VB.NET syntax, it doesn't have anything resembling the null coalescing operator like C#'s ?? operator. The Iif() function can write more compact If statements but they rarely work for null references since both arguments are evaluated.
In general, try to favor null references as a debugging aid. They throw a nice exception when some other code you didn't write is calling yours but messed up something like initialization. Silently propagating programming bugs leads to hard to diagnose failure. Like a NullReferenceException that's far removed from the cause. Or worse, bad data. You could perhaps address your scenario with a NotAPlan and a NoSpouse object, objects that solely exists to avoid null reference exceptions and logically mean "no plan assigned, no spouse defined". A reference that can be null is otherwise nothing more than a reference + a boolean. Don't skip the bool.
There is no null-safe dot notation in VB versions prior to 14 (Visual Studio 2015).
A nicer way of dealing with possible null values, without having too many ifs, is to use AndAlso (short-circuiting And):
If Case.Plan IsNot Nothing _
AndAlso Case.Plan.Person IsNot Nothing _
AndAlso Case.Plan.Person.Name = "Something" Then
'Do something here
End If
Another options is to use the Null Object Pattern. But that would only be possible with your own data types and would require some changes in your code.
Edit:
To answer your question about LINQ, it can't help you with this. LINQ's goal is to help you query sets of data (lists, arrays, etc.). If you try to query your data with LINQ you'll have the same problem if one of your objects is null.
精彩评论