【发布时间】:2021-03-12 14:23:06
【问题描述】:
我正在使用 CSVHelper 库来读取 CSV 文件。但这不是本文的目的
请参考下面的代码
public class Reader
{
public IEnumerable<CSVModel> Read(string file)
{
using var reader = new StreamReader(@"C:\Users\z0042d8s\Desktop\GST invoice\RISK All RISKs_RM - Copy.CSV");
using var csv = new CsvReader(reader, CultureInfo.InvariantCulture);
IEnumerable<CSVModel> records = csv.GetRecords<CSVModel>();
return records;
}
}
上述方法中的 csv.GetRecords 使用 yield return 并在读取后立即返回每个 CSV 行,而不是等到读取整个 CSV 文件才返回(从 CSV 流数据)
我有一个消费者类,顾名思义,它使用 Read 方法返回的数据。
class Consumer
{
public void Consume(IEnumerable<CSVModel> data)
{
foreach(var item in data)
{
//Do whatever you want with the data. I am gonna log it to the console
Console.WriteLine(item);
}
}
下面是调用者
public static void main()
{
var data = new Reader().Read();
new Consumer().Consume();
}
希望我没有失去你。
我面临的问题如下
由于上面的数据变量是 IEnumerable,它将被延迟加载(换句话说,只要不迭代,它就不会读取 CSV 文件)。但是,当我调用 Consume() 方法时,该方法迭代数据变量,强制在 Read() 方法中读取 CSV 文件,使用语句中的 reader 和 csv 对象将被丢弃ObjectDisposed 异常。
另外,我不想删除 using 块之外的 reader 和 csv 对象,因为它们应该被丢弃以防止内存泄漏。
异常信息如下
System.ObjectDisposedException: 'GetRecords<T>() returns an IEnumerable<T>
that yields records. This means that the method isn't actually called until
you try and access the values. e.g. .ToList() Did you create CsvReader inside
a using block and are now trying to access the records outside of that using
block?
而且我知道我可以使用贪婪运算符 (.ToList())。但我希望延迟加载工作。
如果有什么出路,请提出建议。
提前致谢。
【问题讨论】:
-
不是 using 关键字应该定义一个代码块吗?
using(var x = ) { /* code in scope */ } -
@SteveB 从 C# 8 开始,不再是。 C# 8 引入了using declarations,它只是一些自动生成 using 块的语法糖,让您不再需要。
-
@MindSwipe:很高兴知道。这意味着在外部范围的末尾隐式调用了被处置的?
-
@SteveB 是正确的。