Как удовлетворить CA2202 (не удалять объекты несколько раз)

Этот вопрос может показаться вам дубликат CA2202, как решить этот случай, который имеет принятый ответ. Но вы можете понять, что принятый ответ имеет 5 голосов, основанных на низком качестве. Также любые другие голосовые ответы на самом деле не решают проблему. Большинство из них объясняет, как подавить правило или дебаты о том, как неправильно это правило и почему мы должны его игнорировать. Поскольку это правило существует, должен быть способ удовлетворить его, и я ищу поддержку сообщества для решения этой проблемы.

Я пытаюсь понять, как удовлетворить CA2202 в следующем коде. Я понимаю, что проблема здесь заключается в том, что использование инструкции также предоставляет объект encryptedStream . Но если я удалю окончательную часть, он начнет бросать CA2000

Итак, каков правильный способ написания его в соответствии с CA2202 и CA2000

byte[] result; MemoryStream encryptedStream = null; try { encryptedStream = new MemoryStream(); using (var cryptStream = new CryptoStream(encryptedStream, cryptoTransform, CryptoStreamMode.Write)) { cryptStream.Write(inputInBytes, 0, inputInBytes.Length); cryptStream.FlushFinalBlock(); result = encryptedStream.ToArray(); } } finally { encryptedStream?.Dispose(); } string output = Convert.ToBase64String(result); 

Это буквальный ответ на ваш вопрос, поскольку он не будет выдавать предупреждения CA, не подавляя их, и будет когда-либо вызывать каждый Dispose один раз:

 MemoryStream encryptedStream = null; CryptoStream cryptStream = null; try { encryptedStream = new MemoryStream(); cryptStream = new CryptoStream(encryptedStream, cryptoTransform, CryptoStreamMode.Write); cryptStream.Write(inputInBytes, 0, inputInBytes.Length); cryptStream.FlushFinalBlock(); result = encryptedStream.ToArray(); } finally { if (cryptStream != null) { cryptStream.Dispose(); } else { if (encryptedStream != null) encryptedStream.Dispose(); } } string output = Convert.ToBase64String(result); 

Но любой разработчик, заслуживающий их соли, должен взглянуть на это и пойти «хм, это похоже на то, что они не знали, using , я бы лучше переписал это». Не делайте этого в производственном коде. Подавить предупреждение. Получение кода, подобного этому правильному (и если оно остается правильным перед лицом изменений), на самом деле сложнее, чем писать код, который использует using с подавлением ложных предупреждений (действительно, я не совсем уверен, что приведенный выше код верен!). Это в первую очередь поражает весь статический анализ кода: писать надежный код. Вы должны увидеть анализ кода как инструмент, а не арбитр правильности.

На самом деле, действительно, подавляйте предупреждение. Предупреждение неверно. Это нормально. 🙂

Сделайте поиск в Google для «вложенного использования CA2202», и вы найдете десятки сообщений stackoverflow и сообщений MSDN по этой проблеме. https://www.google.com/search?q=ca2202+nested+using

В конечном счете, CA2202 и CA2000 ограничены, потому что они не могут понять поведение вложенных объектов IDisposable. Некоторые streamи могут быть сконфигурированы так, чтобы оставить основной stream открытым, но обычно этого не происходит. Подавление действительно является правильным решением. Проблема в том, что вы пытаетесь быть хорошим гражданином, поэтому вы пытаетесь выполнить предупреждения, которые вам даны. Но статический анализ просто недостаточно умен, чтобы справиться с этим.