如何满足CA2202(不要多次处理对象)

3

我正在尝试解决以下代码中如何满足CA2202的问题。我理解这里的问题是,using语句也会释放encryptedStream对象。但如果我删除finally部分,它就开始抛出CA2000

那么,符合CA2202和CA2000要求的编写方式是什么呢?

这个问题可能看起来与CA2202,如何解决此问题重复,该问题有一个被接受的答案。但你可能会意识到,该答案基于质量差,有5个反对票。此外,任何其他得票较高的答案实际上都没有解决问题。其中大多数解释了如何禁止规则或争论为什么该规则错误以及我们应该忽略它。由于该规则存在,应该有一种方法来满足它,我正在寻求社区支持来解决这个问题。

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);

被采纳的答案得分为-5,这是事实,但其他答案有多达60个赞,并且看起来与问题相关。为什么这些答案中没有一个是您的问题的答案,因为它们似乎是相关的呢? - BobRodes
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - cilerler
从什么时候开始?从“处理一次性对象的代码应该是一致的,你不应该知道其他类接管了你创建的一次性对象。”听起来对我很合理,显然也对很多其他人合理。我认为说支持这种观点的大约80个人是为了劫持主题,这种说法似乎不太合理。同样,假设那些不同意你观点的人没有阅读答案也是不合理的。 - BobRodes
@BobRodes 这只是一个有教养的辩论,而不是实际解决方案,我的朋友。我已经在问题中提到了根本原因。但如果你在那个问题中看到了确切的解决方案,请帮助我正确实现代码,这样我就可以通过CA2202而不需要抑制它。我真的理解你的观点,但请试着从我的角度来看。我的任务是满足规则,而不是依赖辩论。我正在寻求社区的支持,而不是试图证明为什么这个问题是有效的,让你们感到不悦。对于占用你的时间,我感到抱歉,并感谢你实际阅读了它。 - cilerler
@GeorgeStocker好了,我做完了。希望能满足大家的需求,并且可以得到最后两个投票来重新开放它。非常感谢您的时间。 - cilerler
显示剩余3条评论
2个回答

6
这是对您问题的直接回答,即不会发出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的代码更加困难(事实上,我不完全确定上面的代码是否正确!)。这违背了首先拥有静态代码分析的全部意义:编写可靠的代码。您应该将代码分析视为工具,而不是正确性的裁决者。


1
谢谢!它符合规则。现在,我可以将其抑制 :) - cilerler

2

真的,真的要压制警告。这个警告是错误的。这样做没问题。:-)

在Google上搜索“CA2202 nested using”,你会找到许多关于这个问题的stackoverflow和MSDN论坛帖子。https://www.google.com/search?q=ca2202+nested+using

最终,CA2202和CA2000的限制在于它们无法理解嵌套的IDisposable对象的行为。一些流可以配置为保留底层流打开,但通常不会这样做。抑制确实是正确的解决方案。问题在于你试图成为一个好公民,所以你试图遵守你所得到的警告。但静态分析并不足够聪明来处理这个问题。


谢谢Moby,我明白抑制是一个选择。但是我想以某种方式满足它。谢谢! - cilerler
1
即使不考虑静态分析,IDisposable.Dispose()的契约也指出:“如果一个对象的Dispose方法被调用多次,则对象必须忽略第一次之后的所有调用”(这不是最近才添加的)。虽然在某些代码中调用Dispose多次可能是错误或疏忽,但在某些情况下是不可避免的,而且良好编写的实现必须无论如何处理这种情况。 - Jeroen Mostert
@ken2k 谢谢!我理解了并在我的问题中说明了。压制已经存在,想要压制的人可以这样做,我们都知道该怎么做。但是我对满足部分很感兴趣。 - cilerler
@cilerler 我在链接的问题中的回答正是如此。它被踩了,因为看起来很丑,但这是唯一的方法。 - Henrik
为什么不引用各个段落并直接链接到它们,而不是发布指向谷歌搜索的链接呢? - George Stocker
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接