Favour Verbose Linq expressions?

2019-07-14 07:04发布

问题:

It occurred to me that I write out linq statements in a simple, but what others may define as verbose manner;

A simple example:

return _entries
    .Where(x => x.Context.Equals(context))
    .Where(x => x.Type == typeof (T))
    .Select(x=>x.Value)
    .Cast<T>()
    .Single();

can be simplified to:

return _entries
    .Where(x => x.Context.Equals(context) && x.Type == typeof (T))
    .Select(x=>(T)x.Value)
    .Single();

[Question] In the long run, which is the better coding practice? i.e. long (and simple) linq chains or short linq chains with more complicated selectors/etc?

It is right to assume that these Linq statements will be optimized by the compiler?

回答1:

In the long run, which is the better coding practice?

I prefer short and simple. It's more readable. The whole point of LINQ is to make the code read more like the logic of the business domain.

It is right to assume that these Linq statements will be optimized by the compiler?

No; the optimization is done by the runtime, not by the compiler. LINQ-to-objects "Where" and "Select" clauses that follow the pattern you describe are optimized into a single "where-select" object at runtime to avoid creating too many iterators. (Though as Jon Skeet discovered, that can sometimes produce situations in which performance is actually degraded; like almost all "optimizations", it's not a win 100% of the time. Unfortunately I can't find Jon's article on that at this moment.)



回答2:

No, it is not right to assume these LINQ statements are optimized by the compiler. The more verbose syntax produces more Enumerator objects, so the two are not equivalent. From a performance standpoint the shorter syntax will be (slightly) better.

However, if you are choosing between the two syntaxes from a readability and coding standpoint, I would go with the first as it shows the steps that are taken better. I always prefer readability above performance, except when you can prove there is a performance bottleneck.

However, there is an OfType<T>() LINQ operator that you might find useful. Your first example, rewritten:

return _entries
    .Where(x => x.Context.Equals(context))
    .OfType<T>()
    .Select(x => (T)x.Value)
    .Single();


回答3:

In the long run the better coding practice is the one that is more readable. If you are concerned about performance, then test both approaches. If it's not worth testing then it's not worth optimizing.



回答4:

I love Linq expression, as it gives a way to express the intent of your code declarativly. It focuses on what you want to achieve rather how to achieve it. So emphasis on the readability of your code.

But replacing some for/foreach blocks by Linq operators may also make the code cumbersome to realize. So I suggest to write your expression as verbose such that you are describing the logic verbally to your co-programmer, e.g. the below expression can be describe as "Return a Single value As of type T Where the entries context is equal to context and type is equal to T". If needed write custom extension methods, like the As<T>() that cast the value to type T.

return _entries
    .Where(x => x.Context.Equals(context) && x.Type == typeof (T))
    .Single (x=> x.Value)
    .As<T>();


标签: c# .net linq clr