Yield关键字为IEnumerable提供了意外的值

问题描述 投票:0回答:1

这是我的代码(扩展方法)

public static IEnumerable<uint> GetFieldVals(this DataSource rs, IEnumerable<string> columnNames, Predicate<uint> shouldRun)
        {
            var rList = new List<uint>();
            if (columnNames.Any())

                foreach (var name in columnNames)
                {
                    rs.GetFieldVal(name, out uint temp);
                    if (shouldRun(temp))
                    {
                        rList.Add(temp);
                    }

                }
            return rList;
        }

这有效。但是,如果我将其更改为此,结果将是生成的集合中的所有最终项目(尽管Count是正确的值)。

public static IEnumerable<uint> GetFieldVals(this DataSource rs, IEnumerable<string> columnNames, Predicate<uint> shouldRun)
    {

            if (columnNames.Any())

                foreach (var name in columnNames)
                {
                    rs.GetFieldVal(name, out uint temp);
                    if (shouldRun(temp))
                    {
                        yield return temp;
                    }

                }
        }

什么给了?

编辑谢谢大家的评论。我写得很匆忙,但是周末很忙,所以我无法正确解决这个问题。我现在就这样做。你们全都100%正确,因为我遗漏了太多。

我正在尝试使用笨拙的DataSource api并使用它创建一个valuenum项目的IEnumerable(使用起来更容易,更灵活)。我正在使用工厂来实现此目的以使其可移植;我的工厂方法实现调用了我在原始帖子中编写的代码。这是我的valueobject外观的一个示例:

public class MyTableDataObject : IDataObject<uint>
{
    public uint ID { get; set; }
    public string Name { get; set; }

    //MOAR properties

    public IEnumerable<uint> SomeCollection { get; set; }

    //MOAR properties

}

当我在valueobject中有某种类型的集合作为属性时(即上面的代码片段中的“ SomeCollection”,就会出现我所谈论的问题)

FWIW,这是我的用于收集列名的代码

    public static IEnumerable<string> ColumnNames
    {
        get
        {

            yield return "COLUMNNAME00";
            yield return "COLUMNNAME01";
            yield return "COLUMNNAME02";
            yield return "COLUMNNAME03";
            yield return "COLUMNNAME04";
            yield return "COLUMNNAME05";
            yield return "COLUMNNAME06";
            yield return "COLUMNNAME07";
            yield return "COLUMNNAME08";
            yield return "COLUMNNAME09";
            yield return "COLUMNNAME10";
            yield return "COLUMNNAME11";
            yield return "COLUMNNAME12";
            yield return "COLUMNNAME13";
            yield return "COLUMNNAME14";
            yield return "COLUMNNAME15";
        }
    }

这里是调用代码。

var rs = new DataSource();
rs.Open("Select * From MyTable");

var dse = new DataSourceEnumerable<uint>(rs, new MyTableDataObjectFactory());

using (var writer = new MyWriterFacade("MyOutput.json"))
{
    var json = new JsonSerializer(); //Newtonsoft.Json lib
    var str = JsonConvert.SerializeObject(dse, Formatting.Indented);
    writer.Write(str);   

}

虽然输出json文件的值大部分是正确的,但是当我使用yield关键字时,每个“ SomeCollection”中都有相同的项目。但是,当我不使用yield并使用更传统的代码时,json输出说明文件中每个项目的正确值。

我希望可以对此有所启发,如果有人可以更好地帮助我解决这个问题。赞赏!

c# ienumerable yield
1个回答
3
投票
所示代码中的唯一实际区别与

timing有关。使用列表版本时,将在调用方法时执行操作。对于yield版本,稍后在该方法的result实际上是iterated。]时调用它。现在:有时可以在调用返回序列的方法与迭代该序列之间进行更改。例如,数据源或字段序列参数的内容可能会更改。或谓词的逻辑可能会更改,通常是由于“捕获的变量”所致。因此:区别在于

call this

的代码,我们看不到。但是:在调用方法和实际对其进行迭代(foreach等)之间寻找timing

© www.soinside.com 2019 - 2024. All rights reserved.