如何在Linq查询中使用收益率

时间:2011-04-21 15:25:59

标签: c# linq yield

我有以下方法:

    public string GetDepartmentTitle(string DepartmentAbbreviation) {
        List<TaxonomyItem> Divisions = TaxonomyFromCMS.GetAllItems(DomainDataConstants.DivisionAndDepartment.TAXONOMY_ID);
        List<TaxonomyItem> Departments = new List<TaxonomyItem>();

        Divisions.ForEach(delegate(TaxonomyItem Division) {
            Departments.AddRange(Division.SubTaxonomyItems);
        });

        TaxonomyItem Result = (from d in Departments
                               where d.Name == DepartmentAbbreviation
                               select d).FirstOrDefault();

        return Result == null ? "" : Result.Title;
    }

它首先读取所有的Divisons(只有3个),但是这些Divides下面有许多Departments作为SubTaxonomyItems。目前,我逐步完成每个部门并提取出每个部门,并将它们放入名为Departments的列表中。然后我使用Linq搜索特定项目。

它的效果很好但是我想跳过/消耗获取子项的第一步。我尝试过以下似乎不起作用的行:

TaxonomyItem Result = (from d in Departments.SubTaxonomyItems

然后我通过某种类型的lambda与Departments.SubTaxonomyItems的foreach包含一个yeild语句。这可能是诀窍,但我无法让它发挥作用。看看yeild语句,如果我做一些扩展方法似乎有办法。但我想看看它是否可以内联完成,并且像下面的伪代码一样:

    public string GetDepartmentTitle(string DepartmentAbbreviation) {
        List<TaxonomyItem> Divisions = TaxonomyFromCMS.GetAllItems(DomainDataConstants.DivisionAndDepartment.TAXONOMY_ID);

        TaxonomyItem Result = (from d in Divisions.ForEach(delegate(TaxonomyItem Division) {
                                 yeild return Divison.SubTaxonomyItems;
                               }) AS Dps
                               where Dps.Name == DepartmentAbbreviation
                               select Dps).FirstOrDefault();

        return Result == null ? "" : Result.Title;
    }

这可能是这种方式还是我没有看到的其他方式?它甚至可以在没有扩展方法的情况下完成吗?

5 个答案:

答案 0 :(得分:12)

首先,只需在查询中添加“from”即可轻松解决问题:

var query = from division in divisions
            from department in division.Departments
            where department.Name == whatever
            select department;

这正是你所做的;它从每个部门中选出部门序列,并将所有这些序列粘合在一起,形成一个长序列的部门。

这为您提供了“拼接一堆序列”场景的灵活语法。但更普遍的是,有时你遇到这种情况:

var bars = from foo in foos
           some complicated query logic here
           select foo.bar;
var abcs = from bar in bars
           some other query logic here
           select bar.abc;

并且您想要弄清楚如何将其转换为单个查询。你可以这样做:

var abcs = from bar in (
               from foo in foos
               some complicated query logic here
               select foo.bar)
           some other query logic here
           select bar.abc;

丑陋,或者你可以这样做:

var abcs = from foo in foos
           some complicated query logic here
           select foo.bar into bar
           some other query logic here
           select bar.abc;

这完全相同,但阅读起来更愉快。此语法称为“查询延续”。

回答您的具体问题:在匿名方法或lambda中放置“yield return”是不合法的。这非常不幸,因为它非常有用。编译器为使匿名函数和迭代器块工作而执行的转换非常复杂,到目前为止,我们总是试图让它们完全协同工作。 (也就是说,你可以将一个lambda放在一个迭代器块中,但是你不能把一个迭代器块放在一个lambda中。)我希望,但不要保证,有一天我们能够修复这个代码并且允许迭代器阻塞lambda。 (请记住,Eric关于未来语言功能的思考仅适用于娱乐目的。)

答案 1 :(得分:2)

看起来你只是想要这样的东西。

public string GetDepartmentTitle(string DepartmentAbbreviation) {
    var items = TaxonomyFromCMS.GetAllItems(DomainDataConstants.DivisionAndDepartment.TAXONOMY_ID); 
    var result = items.SelectMany(item=>item.SubTaxonomyItems).FirstOrDefault(item=>item.Name == DepartmentAbbreviation);
    var text = result !=null  ? result.Title : String.Empty;
    return text;
}

答案 2 :(得分:1)

收益率返回只能用于非常精选(双关语)位置,而Linq查询不是其中之一。幸运的是,你不需要它。

var q = from division in Divisions
        from dps in division.SubTaxonomyItems
        where dps.Name == DepartmentAbbreviation
        select dps.Title;

return q.FirstOrDefault() ?? String.Empty;

答案 3 :(得分:0)

为什么不这样做:

var divisions = TaxonomyFromCMS.GetAllItems
                 (DomainDataConstants.DivisionAndDepartment.TAXONOMY_ID);

var titles = from division in divisions
             from deparment in division.SubTaxonomyItems
             where deparment.Name == DepartmentAbbreviation
             select deparment.Title;

return titles.FirstorDefault() ?? "";

答案 4 :(得分:0)

您正在寻找这个linq吗?

var Result = Divisions.SelectMany(d => d.SubTaxonomyItems).Where(subItem => subItem.Name == DepartmentAbbreviation).FirstOrDefault();