Automaticaly check object nullity before access some member
When we use Linq is very common to check object nullity before access some member
var query =
from t in dc.table
select new {
StringValue = i.Referency1 != null && i.Referency1.Referency2 != null ? i.Referency1.Referency2.StringValue : null,
IntValue = i.Referency1 != null && i.Referency1.Referency2 != null ? (int?)i.Referency1.Referency2.IntValue : null,
};
So.. with a new syntax we can simplify the access:
var query =
from t in dc.table
select new {
StringValue = i.Referency1?.Referency2?.StringValue,
IntValue = i.Referency1?.Referency2?.IntValue,
};
If the object to be acessed is null, the result will be automaticaly null, the result type becomes Nulable<> for value types.
Some other advantages:
someObject?.Close();
Insted of
if (someObject != null) someObject .Close();
myEvent?.Invoke(this, EventArgs.Empty);
Insted of
if (myEvent != null) myEvent(this, EventArgs.Empty);
Thanks
13 comments
-
David Boarman
commented
Do you not know how to use Any()?
-
Mart Sõmermaa
commented
Note that the same feature has also been requested in http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/2372576-create-a-null-safe-dereference-operator and http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/2873905-null-non-coalescing-operator. So the vote count from there (61 as of 2013-03-23) should be added here (and the duplicates should perhaps be closed?)
-
Jamie Nordmeyer
commented
I posted this idea for .NET 4.0 when it was still in development, and was told that it wouldn't be included because, if I recall correctly, "they couldn't decide how to parse it". I didn't buy that then, either. ;) I would absolutely LOVE to see this in the language.
-
ChrisF
commented
I really like the idea for this, not just for C# (I'd like to see it in JS too).
It would remove loads of boilerplate making code more concise.Some might argue that if your code is not overstepping responsibility boundaries then you wouldn't need this anyway, but I still come across cases where it'd be very handy.
-
Sam
commented
Eric Lippert has mentioned previously that they've considered the ".?" operator.
Please, please, please make this operator a reality. I write code, literally every day, where this would be useful and make the code cleaner and easier to understand.
-
Jesse McClusky
commented
I'd prefer .? instead. (:
-
Qwertie
commented
Yes, this operator exists in groovy where it is called the "safe natigation operator". Please note that the Groovy operator has a natural limitation, described here:
http://www.nearinfinity.com/blogs/jeff_kunkle/groovys_safe_navigation_operat.html
I believe this limitation can be overcome, however, by giving it a *lower* precedence than the dot operator and some special magic. For example, consider this code:
string x = Form?.Location.X.ToString();
If Location is a point (and X is an integer) then we have a natural inclination to use the dot operator instead of "?."; however, this is dangerous if "?." has the obvious interpretation:
string x = (Form?.Location).X.ToString();
...becomes...
string x = (Form != null ? Form.Location : (Point?)null).X.ToString();Clearly the null-dot (aka safe navigation) operator is ineffective if it is interpreted this way (when Form is null). However, if we interpret "?." as having lower precedence than "." then we have
string x = Form?.(Location.X.ToString());
Placing parenthesis after a dot like this isn't actually legal of course, I am simply writing it this way to convey the idea that the ?. operator has to consider the dots that come after it. The compiler then transforms the expression into
string x = (Form != null ? Form.Location.X.ToString() : null);
Of course, if 'Form' is a property then it should only be evaluated once, so the compiler must create a temporary variable. Assuming the notation "Form:tmp" declares a variable "tmp" to hold the value of "Form" then this would be
string x = (Form:tmp != null ? tmp.Location.X.ToString() : null);
-
LosManos
commented
This exists in a language; Ruby? Python? I just can't remember which. I believe the syntax is .?
Like
theStreet = customer.?Address.?Street;combined with Coalesce ?? the syntax would be
theStreet = customer.?Address.?Street ?? "Unknown"; -
gzak
commented
Actually, I should add: by doing something like someObject?.Result, if someObject is not null, it will return the value of the Result property as normal, but as a Nullable<int>. Only if someObject is null does the ?. operator make a difference by returning a null of type Nullable<int>. This is where the ?? operator comes in, to clean up the returned Nullable<int> and turn it back into a regular int (so that you can use it with existing code that expects the usual int rather than Nullable<int>).
-
gzak
commented
Pavel,
Not quite: my intent was to simplify the null check of accessed objects along the way to the destination property, not just to clean up the final property value. In particular, suppose in my example someObject was null, and the Result property on that object was of type int (not Nullable<int>). What would someObject?.Result return? Obviously null of type Nullable<int>, but if I actually wanted to preserve the original type of the property (int) by providing some default value, I was pointing out that you can simply tack on ?? 0 using the existing null coalescing operator to do so.
Basically, something like a ?. null-checked property accessor operator (what would it do if the right hand side was a method, or a side-effect-full property getter? Not sure, but it's an interesting edge case to consider...) coupled with the existing ?? null coalescing operator would go very far in alleviating developers from gratuitous null-checks throughout the code.
Though that's an interesting example of automatic null-checking in LINQ2SQL, I didn't know that. Is it still true in Entity Framework? Also, I know from experience that this type of automatic null-checking is /not/ supported by LINQ2XML. But by providing a ?. operator, we would have a general way of handling such null checking anywhere in the code, not just in LINQ.
-
Pavel
commented
Hey, you actually CAN do this in LINQ-to-SQL. For example:
var query =
from user in dataContext.Users
select new
{
Name = user.Name,
CategoryName = user.Category.Name
};
var users = query.ToList();turns into the following sql:
select u.name, c.name
from users u
left join category c on c.id = u.categoryidso it outputs null as categoryname for users not having categories, and the code executes just fine.
for value types, you have to make a trick though:
var query =
from user in dataContext.Users
select new
{
Name = user.Name,
CategoryCreatedOn = (DateTime?)user.Category.CreatedOn
};in order to allow nulls linq2sql gets from the DB be bound to the model correctly.
You can't do this with in-memory objects, though.
-
Pavel
commented
gzak,
you can do this:
int result = someObject ?? 0;
-
gzak
commented
Absolutely. And coupled with the already existing "??" operator, you can salvage Nullable<> types back to value types:
int result = someObject?.Result ?? 0;