This project is read-only.

(master 22May) Some dissapointment regarding ?. expansion

Topics: APIs, C# Language Design, General
May 28, 2014 at 8:20 AM
Edited May 28, 2014 at 8:21 AM

The ?. operator is a very nice development, but iti is implemented as a hack.
for Example:
using System;
using System.Linq.Expressions;
public class C(int x) {
    public void M() {
        var a = default(string);
        var len = a?.Length;
        Expression<Func<string,int?>> e = (s)=>s?.Length;
There is no special Expression type for ?. I would expect as SafeMemberExpression or something.

The expression e in prevoius sample is expanded like:
        ParameterExpression parameterExpression = Expression.Parameter(typeof(string), "s");
        Expression<Func<string, int?>> expression = Expression.Lambda<Func<string, int?>>(Expression.Condition(Expression.NotEqual(parameterExpression, Expression.Constant(null, typeof(string))), Expression.New(methodof(int?..ctor(!0)), new Expression[] {
            Expression.Property(parameterExpression, methodof(string.get_Length()))
        }), Expression.Constant(null, typeof(int?))), new ParameterExpression[] {
Wouldn't be a lot cleaner to implement a new Expression node type?

Just Imagine a LINQ Query Provider having to deal with this expanded form!!!
May 28, 2014 at 9:00 AM
Edited May 28, 2014 at 9:00 AM
We have our own custom LINQ to SQL provider and I will definitely be happier if a custom node type is added:

The main reason is that our provider translates LINQ to SQL (as many others) and translates many . operators to left outer joins.

So this query:
Will be translated to
SELECT c.Name 
FROM PersonDN p
LEFT OUTER JOIN CountryDN c on p.idCountry = c.Id 
And will return null whether your have no name or no country. Null propagation is already built-in into SQL and keeping C# semantics is just too difficult in the general case.

Currently you could also write:
Database.Query<PersonDN>().Select(p=>p.Country == null ? null: p.Country.Name)
And will return exactly the same values, but with a little bit uglier SQL query.
FROM PersonDN p
LEFT OUTER JOIN CountryDN c on p.idCountry = c.Id 
The problem is that developers are going to be using ?. in the queries just in case, even if . has the same semantics when translated to SQL outer joins.

When that happen, I don't want to create horrible queries, neither I would like to be forced to decompile the generated ConditionalExpression to guess if it looks like a null propagating operator.

Another problem with this approach is that, when the expression is compiled, it will generate two accesses (in the simplest case) to the properties.
May 28, 2014 at 3:02 PM
Well, I certainly hope that both LINQ to SQL and the Entity Framework will be updated to deal with this efficiently...