Предупреждение «Доступ к удаленному закрытию» в операторе использования - PullRequest
0 голосов
/ 25 января 2019

Я использую «оператор использования» для обеспечения правильной очистки StreamWriter.

using (StreamWriter fout = new StreamWriter(tempFile))
{
    data.ForEach(line => fout?.WriteLine(line));
}

Я получаю предупреждение ReSharper «Доступ к удаленному закрытию», которое, как я понимаю, связано с тем, чтопеременная fout может быть закрыта.Я понимаю, что в некоторых случаях это может произойти, но в этом случае возможно ли удаление fout при вызове WriteLine?

1 Ответ

0 голосов
/ 25 января 2019

Добро пожаловать в переполнение стека.

Предупреждение Access to disposed closure от ReSharper должно появляться только тогда, когда LINQ с задержкой выполнения захватывает ссылку на замыкание, которое может быть удалено до выполнения.

В данном случае это зависит от того, какой метод ForEach вы вызываете.Если вы вызываете List.ForEach, значит, вы не составляете цепочку отложенного выполнения, поэтому fout, очевидно, будет действительным для каждого вызова.ReSharper, безусловно, должен знать лучше, когда речь заходит об этом методе.

Но есть и другие ForEach методы, в том числе и пользовательские, о которых ReSharper может не знать или которые на самом деле могут быть отложены.Если они хорошо написаны, они будут блокироваться до завершения, но я видел пользовательские методы расширения ForEach, которые этого не делают.Так как ReSharper не может знать наверняка, пока код не сообщит ему аннотацию InstantHandle к параметру действия, он предупредит вас.

Если вы работаете с List.ForEach здесьтогда я бы посоветовал вам отказаться от старого доброго заявления foreach.Что касается других расширений, выясните, блокирует ли оно или есть ли вероятность, что оно будет откладывать выполнение при любых обстоятельствах.Observable.ForEach и Parallel.ForEach оба, кажется, блокируют выполнение, пока коллекция не будет полностью обработана или источник событий не закроется.Другой код может этого не делать, и отслеживание ошибок может быть проблемой после этого.Проверьте источник для метода, если можете, или обратитесь к разработчику библиотеки, если вы не можете получить доступ к источнику.

Как только вы установили, что этот ForEach определенно заблокируется иникогда не откладывает выполнение, тогда вы можете пойти дальше и подавить предупреждение:

// ReSharper disable AccessToDisposedClosure
data.ForEach(line => fout?.WriteLine(line));
// ReSharper restore AccessToDisposedClosure
...