(master 22May) Some dissapointment regarding ?. expansion

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

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[] {
            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 at 8:00 AM
Edited May 28 at 8: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:
Database.Query<PersonDN>().Select(p=>p.Country.Name)
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.
SELECT (CASE WHEN p.idCountry IS NULL THEN NULL ELSE c.Name  END) 
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 at 2:02 PM
Well, I certainly hope that both LINQ to SQL and the Entity Framework will be updated to deal with this efficiently...