开发者

Null coalescing within an invocation chain

If I have a long list of objects that each has the possibility of returning null within a "Linq where" clause, e.g.

 SomeSource.Where(srcItem=>(srcItem.DataMembers["SomeText"].Connection.ConnectedTo as Type1).Handler.ForceInvocation == true));

the indexer can return n开发者_如何学编程ull and the "as" operator may return null. It is possible that the object does not have a connection (ie. The property is null). If a null is encountered anywhere, I would like the where clause to return "false" for the item being evaluated. Instead, it aborts with a null reference exception.

It appears to me that this would be contrived to express within a single C# expression. I don't like to create a multi line statement or create a separate func for it. Is there some use of the null coalescing operator that I'm missing?


You're looking for the .? operator (or is it ?.—one of those, anyway), which does not exist in C# (though it is an often-requested feature, according to Eric Lippert).

The only possible suggestion I have is to write a method that takes an expression and uses it to check for any nulls. But this will come at a performance cost. Anyway, it might look like:

T TryOrDefault<T>(Expression<Func<T>> expression)
{
    // Check every MemberExpression within expression one by one,
    // looking for any nulls along the way.

    // If a null is found, return default(T) or some default value.

    // Otherwise...
    Func<T> func = expression.Compile();
    return func();
}


Using the andand operator from Ruby as inspiration, you could create an extension method that acts as a null guard.

public static U AndAnd<T, U>(this T obj, Func<T, U> func)
{
    return obj == null ? default(U) : func(obj);
}

Your original code could then be rewritten as follows:

SomeSource.Where(srcItem => (srcItem.AndAnd(val => val.DataMembers["SomeText"]).AndAnd(val => val.Connection).AndAnd(val => val.ConnectedTo) as Type1).AndAnd(val => val.Handler).AndAnd(val => val.ForceInvocation));

Do be careful when returning non-boolean value types using this method - make sure you are familiar with the values returned by default(U).


create a separate func for it

This is the way to go. Do not be allergic to proper techniques. Methods you create are no more expensive (at runtime, and conceptually) than anonymous methods.


A while ago I wrote a project that mimics AndAnd that relies on DynamicProxy. It works fine, although I've not used it in prod. The only drawback is that it requires all of the members to be virtual or the returned types to be an interface so DynamicProxy can do its magic.

Check it here https://bitbucket.org/mamadero/andand/overview

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜