C# 对收益率回报率的担忧以及从外汇储备中突破

C# 对收益率回报率的担忧以及从外汇储备中突破,c#,.net,C#,.net,有没有一个合适的方法来打破僵局,让IEnumerable知道我已经完成了,它应该清理干净 考虑以下代码: private static IEnumerable<Person> getPeople() { using (SqlConnection sqlConnection = new SqlConnection("...")) { try { sqlConn

有没有一个合适的方法来打破僵局,让IEnumerable知道我已经完成了,它应该清理干净

考虑以下代码:

    private static IEnumerable<Person> getPeople()
    {
        using (SqlConnection sqlConnection = new SqlConnection("..."))
        {
            try
            {
                sqlConnection.Open();
                using (SqlCommand sqlCommand = new SqlCommand("select id, firstName, lastName from people", sqlConnection))
                {

                    using (SqlDataReader reader = sqlCommand.ExecuteReader())
                    {
                        while (reader.Read())
                            yield return new Person(reader.GetGuid(0), reader.GetString(1), reader.GetString(2));
                    }
                }
            }
            finally
            {
                Console.WriteLine("finally disposing of the connection");
                if (sqlConnection.State == System.Data.ConnectionState.Open)
                    sqlConnection.Close();
            }
        }
    }
private静态IEnumerable getPeople()
{
使用(SqlConnection SqlConnection=newsqlconnection(“…”)
{
尝试
{
sqlConnection.Open();
使用(SqlCommand SqlCommand=newsqlcommand(“从人中选择id、firstName、lastName”,sqlConnection))
{
使用(SqlDataReader=sqlCommand.ExecuteReader())
{
while(reader.Read())
返回新的Person(reader.GetGuid(0)、reader.GetString(1)、reader.GetString(2));
}
}
}
最后
{
Console.WriteLine(“最终处理连接”);
if(sqlConnection.State==System.Data.ConnectionState.Open)
sqlConnection.Close();
}
}
}

如果使用者没有从foreach中断,则一切正常,读取器将返回false,while循环将结束,函数将清理数据库命令和连接。但是,如果调用方在我完成之前从foreach中断会发生什么情况呢?

您可以使用该语句

yield break;
要尽早打破收益循环,但我认为您的代码揭示了一个误解。。。 当您使用“using”语句时

using (SqlConnection sqlConnection = new SqlConnection("...")) 
{
   //  other stuff
}

在编译的IL代码中,您会自动得到一个try finally块,finnaly块将调用Dispose,而在Dispose代码中,连接将关闭

让我们看看我是否明白你的问题

foreach(Person p in getPeople())
{
    // break here
}

由于foreach关键字,枚举数被正确地释放。在处理枚举数期间,getPeople()的执行被终止。因此,连接已正确清理。

问得好。你不必为此担心;编译器为您处理它。基本上,我们要做的是将finally块的清理代码放入生成的迭代器上的特殊清理方法中。当控件离开调用方的foreach块时,编译器生成代码,调用迭代器上的清理代码

一个简化的例子:

static IEnumerable<int> GetInts()
{
    try { yield return 1; yield return 2;} 
    finally { Cleanup(); }
}
对。迭代器块生成为一个类,该类具有调用Cleanup的Dispose方法,然后foreach循环生成为类似于:

{
  IEnumerator<int> enumtor = GetInts().GetEnumerator();
  try
  {
    while(enumtor.MoveNext())
    {
      i = enumtor.Current;
      break;
    }
  }
  finally
  {
    enumtor.Dispose();
  }
}
{
IEnumerator枚举器=GetInts().GetEnumerator();
尝试
{
while(枚举器.MoveNext())
{
i=枚举器。当前;
打破
}
}
最后
{
Dispose()枚举器;
}
}
因此,当中断发生时,最终由处理器接管,并调用处理器

如果您想要更多关于我们在设计此功能时考虑的一些奇怪的角落案例的信息,请参阅我最近的一系列文章

另请参见
{
  IEnumerator<int> enumtor = GetInts().GetEnumerator();
  try
  {
    while(enumtor.MoveNext())
    {
      i = enumtor.Current;
      break;
    }
  }
  finally
  {
    enumtor.Dispose();
  }
}