Linq混合扩展和查询语法

时间:2011-03-01 15:36:08

标签: c# linq c#-4.0

我更喜欢使用扩展方法进行基本的LINQ操作:Where()Select,但对于复杂的Select()SelectMany(),尤其是OrderBy().ThenBy()语句我发现查询语法更具可读性和自然性。

今天我发现自己有以下问题:

from c in _myObject.ObjectsParent.ParentsEnumerable
                    .Where(c =>
                        c == anotherObject || c.Parent == anotherObject)
from q in c.MyObjectsEnumerable
orderby c.SortKey, q.Description
select new { Item = q, Text = c.Description + " -> " + q.Description };

混合查询和扩展语法是否危险(出于可读性,可维护性或任何其他原因)?

这有可能是非常主观的,如果是,如果它不符合一个好的主观问题的要求,我很抱歉。如果我能改进它,请告诉我!

6 个答案:

答案 0 :(得分:6)

  

混合查询和扩展语法是否危险(出于可读性,可维护性或任何其他原因)?

我看到的最大危险是代码中可能会增加“惊喜”,尤其是在其他开发人员查看时。

从编译的角度来看,查询语法直接转换为扩展方法调用,因此这里不一定存在技术问题。但是,这可能会增加额外的方法调用,乍一看,许多开发人员都不会这样做。 可能导致潜在的可维护性问题。

话虽如此,如果谨慎而有充分理由,我并不认为混合语法存在真正的问题。这实际上很常见 - 例如,如果你想用查询语法编写,但需要完全评估,它通常用括号括起来添加.ToList() - 或者如果你想使用带有查询语法的PLINQ,它通常是{ {1}},这在技术上也是混合语法......

答案 1 :(得分:3)

你可以做这样的事情,让事情变得更容易。

var firstQuery =  _myObject.ObjectsParent.ParentsEnumerable
                 .Where(c => c == anotherObject || c.Parent == anotherObject);

var secondQuery = from q in firstQuery.MyObjectsEnumerable
                  orderby firstQuery.SortKey, q.Description
                  select new { Item = q, 
                               Text = firstQuery.Description + " -> " + q.Description };

现在您的查询没有混合

答案 2 :(得分:3)

这是一种判断,但许多“最佳实践”类型的问题往往是,至少在开始时。我的意见是你应该在一个声明中使用其中一个。不是因为混合中固有的任何“危险”,而是为了清晰起见。

在这种特殊情况下,where子句非常简单,我会将其重构为查询语法。

但是有些情况无法在查询语法中优雅地表达。如果只是不可避免地混合语法,那么如果将方法链拆分为自己的变量,那么查询将(再次IMO)更具可读性,然后在查询语法语句中简单地引用该变量。用你的模特作为模特:

//The method chain can be pulled out as its own variable...
var filteredParents = _myObject.ObjectsParent.ParentsEnumerable
                    .Where(c => c == anotherObject || c.Parent == anotherObject);

//...which you can then substitute in a now purely query-syntax statement
from c in filteredParents
from q in c.MyObjectsEnumerable
orderby c.SortKey, q.Description
select new { Item = q, Text = c.Description + " -> " + q.Description };

答案 3 :(得分:2)

我不认为混合是危险的,它认为它取决于什么是更可读,查询语法是非常可读的,但不是灵活的,所以混合一些链接似乎是一个很小的代价。我想答案是你是否认为以下完全链接比你写的更容易阅读,我个人认为你的更容易阅读。

   _myObject.ObjectsParent
            .ParentsEnumerable
            .Where(c => c == anotherObject || c.Parent == anotherObject)
            .SelectMany(c => c.MyObjectsEnumerable, (c, q) => new {c, q})
            .OrderBy(t => t.c.SortKey)
            .ThenBy(t => t.q.Description)
            .Select(t => new {Item = t.q, Text = t.c.Description + " -> " + t.q.Description});

答案 4 :(得分:1)

我使用扩展方法,我的同事使用查询语法。没有区别。

但是我会说你应该将大型查询分解为较小的查询以进行调试和阅读,因为通常没有时间成本。

答案 5 :(得分:1)

我自己完成了这项工作(虽然不是。但是,但是对于.Cast)我会说这很大程度上取决于你所使用的扩展方法。

e.g。我觉得完全有资格使用.Cast,因为它在语法糖(AFAIK)中不可用,但可能会避免。因为它在查询语法中有表示。

话虽如此,我可能会使用.Select来改变查询中的数据......但我有点像个虐待狂。