如何在Linq查询中使用Yield

本文关键字:Yield 查询 Linq | 更新日期: 2023-09-27 17:50:42

我有以下方法:

    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;
    }

它首先读取所有的division(只有3个),但是这些division下面有许多department作为SubTaxonomyItems。目前,我通过每个部门和提取出每个部门,并把它们放在一个名为部门列表。然后我使用Linq来搜索特定的项目。

它工作得很好,但我想跳过/消费获得子项的第一步。我尝试了下面这行,但似乎不起作用:

TaxonomyItem Result = (from d in Departments.SubTaxonomyItems

然后我可能通过某种lambda与每个系的foreach。包含yield语句的SubTaxonomyItems。这可能是诀窍,但我没能成功。查看yield语句似乎可以有一种方法,如果我做一些扩展方法。但我想看看它是否可以内联,像下面的伪代码:

    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;
    }

这可能是这样的,还是我没有看到的其他方式?不使用扩展方法也能实现吗?

如何在Linq查询中使用Yield

首先,您可以通过在查询中添加另一个"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对未来语言特性的思考仅用于娱乐目的。)

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

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;
}

Yield return只能在非常选择(双关语!)的位置使用,而Linq查询不是其中之一。幸运的是,你在这里不需要它。

var q = from division in Divisions
        from dps in division.SubTaxonomyItems
        where dps.Name == DepartmentAbbreviation
        select dps.Title;
return q.FirstOrDefault() ?? String.Empty;

为什么不直接做:

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() ?? "";

这是您要找的链接吗?

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