.net 使用返回IEnumerable

.net 使用返回IEnumerable,.net,delegates,using-statement,deferred-execution,.net,Delegates,Using Statement,Deferred Execution,我遇到了一个很有意思的问题。我有这样一个通用方法: public TResult Run<TResult>(Func<SqlDataReader, TResult> resultDelegate) { TResult result; using (SqlDataReader reader = command.ExecuteReader()) // command is SqlCommand with attached SqlConnection {

我遇到了一个很有意思的问题。我有这样一个通用方法:

public TResult Run<TResult>(Func<SqlDataReader, TResult> resultDelegate)
{
   TResult result;

   using (SqlDataReader reader = command.ExecuteReader()) // command is SqlCommand with attached SqlConnection
   {
      result = resultsDelegate(reader);
   }

   // Some other unrelated code (but that's why result has a variable)

   return result;
}
public TResult运行(Func resultDelegate)
{
结果结果;
使用(SqlDataReader=command.ExecuteReader())//命令是带有附加SqlConnection的SqlCommand
{
结果=结果委托(读卡器);
}
//其他一些不相关的代码(但这就是为什么result有一个变量)
返回结果;
}
在一种情况下,
resultDelegate
的返回类型(
TResult
)是
IEnumerable
。问题是
Run
函数由于延迟执行而立即返回,这会处理SqlDataReader。稍后在代码中,当我尝试通读结果时(委托执行
reader.read()
),我得到了一个
InvalidOperationException:当reader关闭时调用read的尝试无效。

我很难找到解决这个问题的最佳方法。我知道我可以返回一个具体的列表,但如果可能的话,我希望避免。我也可以将using语句移动到委托中,但再一次,如果我可以避免对每个委托都这样做,那就太好了。有什么想法吗?

也许:

public TResult Run<TResult>(Func<SqlDataReader, TResult> resultDelegate)
{
   TResult result;

   using (SqlDataReader reader = command.ExecuteReader()) // command is SqlCommand with attached SqlConnection
   {
      result = resultsDelegate(reader);
      if (typeof(TResult) == typeof(IEnumerable<object>)) 
      {
         var enumerable = result as IEnumerable<object>;
         if (enumerable != null) 
         {
            result = enumerable.ToList();  
         }
      }
   }

   // Some other unrelated code (but that's why result has a variable)

   return result;

}
public TResult运行(Func resultDelegate)
{
结果结果;
使用(SqlDataReader=command.ExecuteReader())//命令是带有附加SqlConnection的SqlCommand
{
结果=结果委托(读卡器);
if(typeof(TResult)=typeof(IEnumerable))
{
var enumerable=结果为IEnumerable;
if(可枚举!=null)
{
结果=可枚举的.ToList();
}
}
}
//其他一些不相关的代码(但这就是为什么result有一个变量)
返回结果;
}

有趣的想法——你强迫它成为一个具体的列表,但超出了委托的范围。我认为在这种情况下,它会产生隐藏的和意外的后果(列表必须在内存中分配)。如果我必须这样做,那么如果委托返回IEnumerable,我可能会抛出一个异常;这样,很明显实际发生了什么。非常有创意的答案值得称赞。如果你不让读者保持开放,就根本没有办法使用延迟执行。你必须在是的,我理解它必须被分配。我的意思是我更愿意在代码中的其他地方进行分配,在那里它更加明确和明显。这很容易隐藏它已经被分配的事实。