gpt4 book ai didi

c# - 代码分析规则 CA2000/CA 2202

转载 作者:太空狗 更新时间:2023-10-29 21:18:46 25 4
gpt4 key购买 nike

我正在努力确保我的编码遵循对象的正确处理,因此我将这些规则作为错误执行。但是我在处理这段代码时遇到了问题

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Xml;

class MyClass
{
public String ToXml()
{
var objSerializer =
new DataContractSerializer(GetType());
var objStream = new MemoryStream();
StreamReader objReader;

String strResult;
try
{
// Serialize the object
objSerializer.WriteObject(objStream, this);

// Move to start of stream to read out contents
objStream.Seek(0, SeekOrigin.Begin);

objReader = new StreamReader(objStream);

try
{
// Read Contents into a string
strResult = objReader.ReadToEnd();
}
finally
{
objReader.Dispose();
}
}
finally
{
if (objStream != null)
{
// objStream.Dispose();
}
}

return strResult;
}
}

如果我注释掉 objStream.Dispose(),我会得到 CA2000,因为我没有处理对象,但如果我删除注释,它就会说我处理了不止一次。

还有什么正在处理这个对象?还是我在处理多个流时做错了?

最佳答案

这种情况现在也让我很烦。每隔几年,我决定通过运行 fxcop 或 Visual Studio 中现在内置的代码分析来刷新代码分析“规则”。

我最初写这段代码的时候,认为我是一个好公民,因为我正确地使用了 usings 来处理:

using (MemoryStream msDecrypt = new MemoryStream())
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Write))
{
csDecrypt.Write(eop.m_Ciphertext, 0, eop.m_Ciphertext.Length);
}

decrypted = msDecrypt.ToArray();
}

此代码块导致 CA2202“不要多次处理对象” 关于此规则的最大讽刺是,它并不是真正与您的代码有关的问题,尽管它是保护您解决其他代码中的问题。 Microsoft 一直有大量关于应如何实现 Dispose 模式 (http://msdn.microsoft.com/en-us/library/b1yfkh5e(v=vs.110).aspx) 的文档。然而,通过查看此代码分析规则 (http://msdn.microsoft.com/en-us/library/ms182334.aspx) 的详细信息,它揭示了此规则的目的

"A correctly implemented Dispose method can be called multiple times without throwing an exception. However, this is not guaranteed and to avoid generating a System.ObjectDisposedException you should not call Dispose more than one time on an object."

简而言之,这条规则就是为了保护自己免受不遵守规则的人的伤害。

自然地,我将代码修改为如下所示:

MemoryStream msDecrypt = new MemoryStream()    
//using (MemoryStream msDecrypt = new MemoryStream())
//{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Write))
{
csDecrypt.Write(eop.m_Ciphertext, 0, eop.m_Ciphertext.Length);
}

decrypted = msDecrypt.ToArray();
//}

现在这个堆栈溢出帖子上的每个人都痛苦地意识到这个新问题,我们的 friend CA2000“在失去作用域之前处理对象” ...所以在这一点上我只是捂着脸一分钟。做了一些谷歌搜索,找到了这篇文章。就在那时我突然意识到,要通过这两个 CA 规则,您需要确保所有代码分支的所有内容都只处理一次。所以我开始着手做这件事,一旦你意识到这是你需要做的,这就不是一个难题。

自然地,代码演变成这样:

MemoryStream msDecrypt = null;
CryptoStream csDecrypt = null;

try
{
msDecrypt = new MemoryStream();
csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Write);

csDecrypt.Write(eop.m_Ciphertext, 0, eop.m_Ciphertext.Length);
csDecrypt.FlushFinalBlock();
decrypted = msDecrypt.ToArray();
}
finally
{
if (csDecrypt != null)
{
csDecrypt.Dispose();
}
else if (msDecrypt != null)
{
msDecrypt.Dispose();
}

}

最后,我的代码没有生成 CA2000 或 CA2202。这个故事的寓意是,由于代码分析规则已经以这种方式发展,USING 语句的值(value)远不如过去。

您可以通过几种不同的方式编写代码来完成这项工作,我只是选择了一种不会将显式调用与 using 语句混合使用的方式,因为我相信这种方式更易于阅读和结构化以某种方式阻止某人只是去包装另一个使用它,从而在不知不觉中导致最初的问题。

关于c# - 代码分析规则 CA2000/CA 2202,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10139718/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com