Это мой код (метод расширения)
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;
}
}
}
Что дает?
РЕДАКТИРОВАТЬ Спасибо всем за ваши комментарии. Я написал это в какой-то спешке, а потом провел напряженные выходные, поэтому я не смог правильно решить эту проблему. Я сделаю это сейчас. Вы все на 100% правы, что я упустил слишком много.
Я пытаюсь взять неуклюжий API DataSource и создать с его помощью IEnumerable элементов valueobject (с которым проще и гибче работать). Я реализую это с помощью фабрики, чтобы сохранить ее переносимость; моя реализация метода фабрики вызывает код, который я написал в моем оригинальном посте. Вот пример того, как выглядит мой 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 (ie «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 в основном правильные, каждый «SomeCollection» содержит одинаковые элементы (я думаю, что это значения SomeCollection последнего элемента), когда я использую ключевое слово yield. Когда я не использую yield и использую более традиционный код, вывод json иллюстрирует правильные значения для каждого SomeCollection в файле.
Это код в фактическом перечисляемом:
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);
}
Я надеюсь, что это проливает некоторый свет на это, если кто-нибудь может сломать это для меня немного лучше. Цени это!