Search code examples
c#.netlinqlinq-to-sqllinq-to-entities

Linq to objects when object is null VS Linq to SQL


I have this Linq to object query:

var result = Users.Where(u => u.Address.Country.Code == 12)

I get an exception if the Address or the Country are null.
Why this query doesn't check if the address is null and just after that procced? This way I won't need to write this terrible query:

var result = Users.Where(u => u.Address != null &&
                              u.Address.Country != null &&  
                              u.Address.Country.Code == 12)

In Linq to SQL the first query wiil do the job(from other reasons of course).

Is the a way to avoid the "null checks" in linq to object?


Solution

  • Unfortunately, "null" is treated inconsistently in C# (and in many other programming languages). Nullable arithmetic is lifted. That is, if you do arithmetic on nullable integers, and none of the operands are null, then you get the normal answer, but if any of them are null, you get null. But the "member access" operator is not lifted; if you give a null operand to the member access "." operator, it throws an exception rather than returning a null value.

    Were we designing a type system from scratch, we might say that all types are nullable, and that any expression that contains a null operand produces a null result regardless of the types of the operands. So calling a method with a null receiver or a null argument would produce a null result. That system makes a whole lot of sense, but obviously it is far too late for us to implement that now; millions upon millions of lines of code have been written that expects the current behaviour.

    We have considered adding a "lifted" member access operator, perhaps notated .?. So you could then say where user.?Address.?Country.?Code == 12 and that would produce a nullable int that could then be compared to 12 as nullable ints normally are. However, this has never gotten past the "yeah, that might be nice in a future version" stage of the design process so I would not expect it any time soon.


    UPDATE: The "Elvis" operator mentioned above was implemented in C# 6.0.