【发布时间】:2020-05-24 00:56:08
【问题描述】:
这是我的代码(扩展方法)
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()) yield break;
foreach (var name in columnNames)
{
rs.GetFieldVal(name, out uint temp);
if (shouldRun(temp))
{
yield return temp;
}
}
}
什么给了?
编辑 谢谢大家的cmets。我写的有点匆忙,然后有一个忙碌的周末,所以我无法正确解决这个问题。我现在就这样做。你们都是 100% 正确的,我遗漏了太多。
我正在尝试使用笨重的 DataSource api 并使用它创建一个 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 中有一些类型的集合作为属性(即上面的 sn-p 中的“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");
//The Generic type on the enumerable indicates the type of the identifier of the items, not that the Enumerable is itself a list of uints. Do not get confused by this!
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”都有相同的项目(我相信这是最后一个项目的 SomeCollection 值)。但是,当我不使用 yield 并使用更传统的代码时,json 输出说明了文件中每个 SomeCollection 的正确值。
这是实际Enumerable中的代码:
public DataSourceEnumerable(DataSource ds, DataObjectFactory<T, DataSource> factory)
{
ds.MoveFirst();
innerList = new List<IDataObject<T>>();
_enumerator = Create(ds, factory, innerList);
}
public static IEnumerator<IDataObject<T>> Create(DataSource ds, DataObjectFactory<T, DataSource> factory,
IList<IDataObject<T>> innerList)
{
while (!ds.Eof)
{
innerList.Add(factory.InitializeDataObject<object, object>(ds));
ds.MoveNext();
}
return new DataSourceEnumerator(innerList);
}
如果有人可以更好地为我分解一下,我希望能对此有所了解。欣赏!
【问题讨论】:
-
请出示你用来调用这个方法的代码,我想看看你用的是什么迭代机制
-
这段代码看起来不错 - 似乎它可能与您调用它的方式有关。你也可以包括调用代码吗?
-
如何迭代
IEnumerable<uint>结果?看起来,您已经在linq方法的循环中某处捕获了变量 -
请制作一个完整、可独立运行的小程序来重现错误并发布。通过这样做,您将自己发现缺陷,或者您将以一种让别人实际运行并理解它的方式呈现代码。您在此处粘贴的代码很好,因此很难理解问题所在。
-
你能说一下为什么在
foreach循环之前调用Any吗?如果集合为空,foreach将跳过正文,因此这似乎是无用的代码。
标签: c# ienumerable yield