Jad*_*ias 17 .net c# using exception yield-return
如果我没记错的话,当我在using SqlConnection
块内使用yield 时,我得到了运行时异常.
using (var connection = new SqlConnection(connectionString))
{
var command = new SqlCommand(queryString, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
// Call Read before accessing data.
while (reader.Read())
{
yield reader[0];
}
// Call Close when done reading.
reader.Close();
}
Run Code Online (Sandbox Code Playgroud)
当我用yield
List 替换这些问题时,我每次迭代都添加了项目.
在内部using StreamReader
块时,我没有发生同样的问题
using (var streamReader = new StreamReader(fileName))
{
string line;
while ((line = streamReader.ReadLine()) != null)
{
yield return line;
}
}
Run Code Online (Sandbox Code Playgroud)
有没有解释为什么例外事件发生在前一种情况而不是后者?这个建筑是否可取?
编辑为了得到我过去做的错误(早期处理)你应该调用下面的第一个方法:
IEnumerable<string> Read(string fileName)
{
using (var streamReader = new StreamReader(fileName))
{
return Read(streamReader);
} // Dispose will be executed before ReadLine() because of deffered execution
}
IEnumerable<string> Read(StreamReader streamReader)
{
string line;
while ((line = streamReader.ReadLine()) != null)
{
yield return line;
}
}
Run Code Online (Sandbox Code Playgroud)
使用其他延迟执行的方法可以实现相同的错误,例如 System.Linq.Enumerable.Select()
请参阅这篇文章,using
了解和问题的详细解释yield
。因为您返回枚举器,所以 using 块在访问任何内容之前就已经销毁了上下文。答案有很好的解决方案,基本上,要么使包装器方法成为枚举器,要么构建一个列表。
using
此外,将读者放在周围(而不是连接)通常更实用,并CommandBehavior.CloseConnection
用于确保读者完成后释放资源。尽管这在您的情况下并不重要,但如果您从方法返回数据读取器,这将确保在处理读取器时正确关闭连接。
using(SqlDataReader reader =
command.ExecuteReader(CommandBehavior.CloseConnection)) {
while (reader.Read())
{
yield reader[0];
}
}
Run Code Online (Sandbox Code Playgroud)