C# using 语句 FileStream 和/或 StreamReader - Visual Studio 2012 警告

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12000136/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 20:01:54  来源:igfitidea点击:

using statement FileStream and / or StreamReader - Visual Studio 2012 Warnings

c#.netdisposeusingvisual-studio-2012

提问by JHubbard80

The new Visual Studio 2012 is complaining about a common code combination I have always used. I know it seems like overkill but I have done the following in my code 'just to be sure'.

新的 Visual Studio 2012 抱怨我一直使用的常见代码组合。我知道这似乎有点矫枉过正,但我​​在我的代码中做了以下“只是为了确定”。

using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
    using (var sr = new StreamReader(fs))
    {
        // Code here
    }
}

Visual studio is 'warning' me that I am disposing of fs more than once. So my question is this, would the proper way to write this be:

Visual Studio 正在“警告”我我不止一次处理 fs。所以我的问题是,写这个的正确方法是:

using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
    var sr = new StreamReader(fs);
    // do stuff here
}

Or should I do it this way (or some other variant not mentioned).

或者我应该这样做(或其他一些未提及的变体)。

var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

using (var sr = new StreamReader(fs))
{
    // Code here
}

I searched several questions in StackOverflow but did not find something that addressed the best practice for this combination directly.

我在 StackOverflow 中搜索了几个问题,但没有找到直接解决此组合最佳实践的问题。

Thank you!

谢谢!

采纳答案by Dan

The following is how Microsoft recommendsdoing it. It is long and bulky, but safe:

以下是Microsoft 建议的做法。它又长又笨重,但安全:

FileStream fs = null;
try
{
    fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
    using (TextReader tr= new StreamReader(fs))
    {
        fs = null;
        // Code here
    }
}
finally
{
    if (fs != null)
        fs.Dispose();
}

This method will always ensure that everything is disposed that should be despite what exceptions may be thrown. For example, if the StreamReaderconstructor throws an exception, the FileStreamwould still be properly disposed.

此方法将始终确保处理所有应处理的内容,而不管可能引发什么异常。例如,如果StreamReader构造函数抛出异常,FileStream仍然会被正确处理。

回答by Daniel Hilgarth

Yes, the correct way would be to use your first alternative:

是的,正确的方法是使用你的第一个选择:

using (FileStream fs = new FileStream(filePath, FileMode.Open,
                                      FileAccess.Read, FileShare.ReadWrite)) 
{ 
    TextReader tr = new StreamReader(fs); 
    // do stuff here 
} 

The reason is the following:
Disposing the StreamReaderonly disposes the FileStreamso that's actually the only thing you need to dispose.

原因如下:
Dispose the StreamReaderonly 处理 the FileStreamso that 实际上是您唯一需要处理的东西。

Your second option (just the inner "using") is no solution as it would leave the FileStreamundisposed if there was an exception inside the constructor of the StreamReader.

您的第二个选项(只是内部的“使用”)不是解决方案,因为FileStream如果StreamReader.

回答by exacerbatedexpert

It's because the way you used StreamReaderdisposes the stream when it is disposed. So, if you dispose the stream too, it's being disposed twice. Some consider this a flaw in StreamReader--but it's there none-the-less. In VS 2012 (.NET 4.5) there is an option in StreamReaderto not dispose of the stream, with a new constructor: http://msdn.microsoft.com/en-us/library/gg712952

这是因为您使用的方式在StreamReader处理流时处理流。所以,如果你也处理流,它会被处理两次。有些人认为这是一个缺陷——StreamReader但它仍然存在。在 VS 2012 (.NET 4.5) 中有一个StreamReader不处理流的选项,有一个新的构造函数:http: //msdn.microsoft.com/en-us/library/gg712952

回答by JHubbard80

As Dan's answer only appears to work with StreamWriter, I believe this might be the most acceptable answer. (Dan's answer will still give the disposed twice warning with StreamReader - as Daniel Hilgarth and exacerbatedexpert mentions, StreamReader disposes the filestream)

由于丹的答案似乎只适用于 StreamWriter,我相信这可能是最可接受的答案。(Dan 的回答仍然会使用 StreamReader 发出已处理的两次警告 - 正如 Daniel Hilgarth 和 exacerbatedexpert 所提到的,StreamReader 会处理文件流)

using (TextReader tr = new StreamReader(new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)))
{
    string line;
    while ((line = tr.ReadLine()) != null)
    {
        // Do work here
    }
}

This is very similar to Daniel Hilgarth's answer, modified to call dispose via the Using statement on StreamReader as it is now clear StreamReader will call dispose on FileStream (According to all the other posts, documentation referenced)

这与 Daniel Hilgarth 的回答非常相似,修改为通过 StreamReader 上的 Using 语句调用 dispose ,因为现在很清楚 StreamReader 将调用 FileStream 上的 dispose (根据所有其他帖子,参考文档)

Update:

更新:

I found this post. For what it is worth. Does disposing streamreader close the stream?

我找到了这个帖子。为了什么它是值得的。 处理 streamreader 会关闭流吗?

回答by paulsm4

Given all the nonsense this (perfectly legitimate!) question generated, this would be my preference:

鉴于这个(完全合法!)问题产生的所有废话,这将是我的偏好:

FileStream fs = null;
TextReader tr= null;
try
{
    fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
    tr= new StreamReader(fs);
    // Code here
}
finally
{
    if (tr != null)
        tr.Dispose();
    if (fs != null)
        fs.Dispose();
}

The links below illustrate perfectly legal syntax. IMO, this "using" syntax is far preferable to nested "using". But I admit - it does notsolve the original question:

下面的链接说明了完全合法的语法。IMO,这种“使用”语法远优于嵌套的“使用”。但我承认 - 它没有解决最初的问题:

IMHO...

恕我直言...

回答by paulsm4

Visual studio is 'warning' me that I am disposing of fs more than once.

Visual Studio 正在“警告”我我不止一次处理 fs。

You are, but that is fine. The documentation for IDisposable.Disposereads:

你是,但那很好。IDisposable.Dispose的文档如下:

If an object's Disposemethod is called more than once, the object must ignore all calls after the first one. The object must not throw an exception if its Disposemethod is called multiple times.

如果一个对象的Dispose方法被多次调用,则该对象必须忽略第一次之后的所有调用。如果多次调用对象的Dispose方法,则该对象不得引发异常。

Based on that, the warning is bogus, and my choice would be to leave the code as it is, and suppress the warning.

基于此,警告是虚假的,我的选择是保留代码原样,并取消警告。

回答by C?ur

Two solutions:

两种解决方案:

A) You trust Reflector or Documentation and you know *Readerand *Writerwill close the underlying *Stream. But warning: it won't work in case of a thrown Exception. So it is not the recommended way:

)你信任的反射器或文件,你知道*Reader,并*Writer会关闭底层*Stream。但警告:它在抛出异常的情况下不起作用。所以这不是推荐的方式:

using (TextReader tr = new StreamReader(new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)))
{
    // Code here
}

B) You ignore the warning as documentation states The object must not throw an exception if its Dispose method is called multiple times.It's the recommended way, as it's both a good practice to always use using, and safe in case of a thrown Exception:

B) 你忽略警告,因为文档说明The object must not throw an exception if its Dispose method is called multiple times.这是推荐的方式,因为它是一个很好的做法,总是使用using,并且在抛出异常的情况下是安全的:

[SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
internal void myMethod()
{
    [...]
    using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
    using (TextReader tr = new StreamReader(fs))
    {
        // Code here
    }
}