Ответ 1
Я не @MarcGravell, но я думаю, что есть одна вещь, которую вам не хватает. Код, который вы вставили, точно не соответствует ссылке, которую вы ссылаетесь. Соответствующий путь кода выглядит следующим образом:
try
{
if (command.Buffered)
{
List<T> buffer = new List<T>();
while (await reader.ReadAsync(cancel).ConfigureAwait(false))
{
buffer.Add((T)func(reader));
}
while (await reader.NextResultAsync().ConfigureAwait(false)) { }
command.OnCompleted();
return buffer;
}
else
{
// can't use ReadAsync / cancellation; but this will have to do
wasClosed = false; // don't close if handing back an open reader;
// rely on the command-behavior.
var deferred = ExecuteReaderSync<T>(reader, func, command.Parameters);
reader = null; // to prevent it being disposed before the caller gets to see it
return deferred;
}
}
finally
{
using (reader) { } // dispose if non-null
if (wasClosed) cnn.Close();
}
Метод может либо возвращать буферный результат (указанный флагом command.Buffered
), либо отложенный итератор. Если Marc должен был обернуть читателя оператором using
и вернуть итератор, он (читатель) был бы удален к тому моменту, когда сайт-сайт выполнил его. Установив читателя на null
(в строке до того, как он вернет отложенный результат), он не позволяет читателю быть удаленным, потому что использование в блоке finally будет переведено на это:
finally
{
IDisposable disposable = reader;
try
{
}
finally
{
if (dispoable != null)
{
disposable.Dispose();
}
}
}
Когда он устанавливает читателя в null
, он не удаляется, и ссылка существует в итераторе, все еще жива, указывая на читателя. Таким образом, он может обедать читателю в обычной кодировке, но сохранить его в живых, если был запрошен отложенный итератор.