使用 MemoryStream 和 CryptoStream 满足代码分析处置规则 [重复]

Posted

技术标签:

【中文标题】使用 MemoryStream 和 CryptoStream 满足代码分析处置规则 [重复]【英文标题】:Satisfying Code Analysing disposal rule with MemoryStream and CryptoStream [duplicate] 【发布时间】:2014-12-16 20:58:37 【问题描述】:

我在满足用于处置 MemoryStream 对象的代码分析规则时遇到问题。

这是我现在的代码:

byte[] bytes;
MemoryStream stream = new MemoryStream();

using (CryptoStream cs = new CryptoStream(stream, transform, CryptoStreamMode.Write))

    cs.Write(buffer, 0, buffer.Length);


bytes = stream.ToArray();
stream.Close();

return bytes;

这会导致警告说流可能被释放两次,或者可能被释放(每个警告一个)。

我也尝试将其包装到 using(MemoryStream stream = new MemoryStream()) 块中。这会导致前一个警告。

最后,删除对Close()Dispose() 的调用会导致后一个警告。

有没有办法同时满足这两个条件?我认为问题是可能会关闭它的异常路径,但我对这些类的工作方式不是很熟悉。

【问题讨论】:

【参考方案1】:

你可以通过使用丢弃所有的流

var bytes = transform.TransformFinalBlock(buffer, 0, buffer.Length);

如果没有流,则无需担心处理它们;)

【讨论】:

手头问题的真正解决方案(问题本身也是完全相同的样本***.com/questions/3831676/…的副本)【参考方案2】:

如果它触发,我个人倾向于在我的源代码中禁止该规则,因为大多数对象都没有被处理两次的问题。但是,如果您想在不压制的情况下满足规则,则需要这样做:

        byte[] bytes = new byte[1024];
        byte[] buffer = new byte[1024];
        ICryptoTransform transform = null;

        MemoryStream stream = null;

        try
        
            stream = new MemoryStream();
            MemoryStream tempStream = stream

            using (CryptoStream cs = new CryptoStream(stream, transform, CryptoStreamMode.Write))
            
                // set stream to null immediately so it doesn't get disposed by finally
                stream = null;

                cs.Write(buffer, 0, buffer.Length);
                bytes = tempStream.ToArray();
            
        
        finally
        
            if (stream != null)
            
                stream.Dispose();
            
        

        return bytes;

【讨论】:

您的代码导致 CA2202 不要多次处理对象.. 不错不错。我将 steam = null 语句移到 using 语句中的第一行代码,FXCop 很高兴。我仍然不喜欢这条规则。 没有警告,但是你现在在设置stream = null后访问stream.ToArray() 是的,更新的答案满足 FXCop 规则并且不使用 Null 对象 我明白你为什么现在就取消规则了 :)【参考方案3】:

CryptoStream 被释放时(当using 块结束时),它在MemoryStream 上调用Close,后者又调用Dispose

因此,您无需亲自致电Dispose(通过using)或Close。这样,stream 只会被处理一次。

MemoryStream stream = new MemoryStream();
using (CryptoStream cs = new CryptoStream(stream, transform, CryptoStreamMode.Write))

    cs.Write(buffer, 0, buffer.Length);
    return stream.ToArray();            

【讨论】:

如果 CryptoStream 构造函数抛出,该代码可能会使 MemoryStream 未处理。 没错,但这并不是(IMO)大问题。一个空的 MemoryStream 不大,最终还是会被 GC 处理。希望 CryptoStream 的 ctor 不太可能抛出。如果不触发代码分析警告之一,我看不到解决方法。 我倾向于禁止这条规则并使用 2 using 语句。但是,如果您不想压制并始终处置,我会使用 try/finally 块更新我的答案以满足规则。 @Blorgbeard MemoryStream 设计为无操作 Dispose,因为它必须保持内部缓冲区(托管字节数组)处于活动状态以供以后调用 ToArray。所以即使不处理“巨大的MemoryStream”也不是问题(很高兴有正确的代码,但没有真正的区别)。

以上是关于使用 MemoryStream 和 CryptoStream 满足代码分析处置规则 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

使用 OpenXML 和 MemoryStream 在 ASP.NET 程序中编辑和保存 .docx

MemoryStream相关知识分享

PCM Wave 文件中的数据长度使用 MemoryStream 和 WaveFileWriter

使用 NAudio 读取包含作品音频的 MemoryStream

优势/劣势 MemoryStream.Position 或 MemoryStream.Seek [重复]

将数组保存到 CoreData Swift