4

ループ内StringWriterに値を書き込むためにメソッドに渡すaを使用しています。foreachこれにより、次の2つの警告が発生していると思います。

CA2000:Microsoft.Reliability:メソッド'ToCsvService.ToCsv()'では、オブジェクト'sw'がすべての例外パスに沿って配置されているわけではありません。オブジェクトへのすべての参照がスコープ外になる前に、System.IDisposable.Dispose onobject'sw'を呼び出します。

CA2202:Microsoft.Usage:オブジェクト'sw'は、メソッド'ToCsvService.ToCsv()'で複数回破棄できます。System.ObjectDisposedExceptionの生成を回避するには、オブジェクトに対してDisposeを複数回呼び出さないでください。

public string ToCsv()
{
    IEnumerable<string> props = GetProperties();
    StringWriter sw = new StringWriter(); // first warning here
    sw.WriteLine(GetHeadings(props));
    WriteValues(props, sw);

    sw.Close();
    string returnCsv = sw.ToString();
    sw.Dispose(); // second warning here

    return returnCsv;
}

GetProperties()適切ではないように思われたため、呼び出されたメソッドのリストから除外しました。

private string GetHeadings(IEnumerable<string> props)
{
    string headings = String.Join(",",
        props.Select(prop =>
            _headings.ContainsKey(prop) ? _headings[prop] : prop));

    return headings;
}

private void WriteValues(IEnumerable<string> props, StringWriter sw)
{
    foreach (object obj in _collection)
    {
        var x = obj.GetType().GetProperties()
            .Where(pi => props.Contains(pi.Name))
            .Select(pi =>
                _format.ContainsKey(pi.Name)
                ? String.Format("{0:" + _format[pi.Name] + "}",
                                pi.GetGetMethod().Invoke(obj, null))
                : pi.GetGetMethod().Invoke(obj, null).ToString());

        string values = String.Join<string>(",", x);

        sw.WriteLine(values);
    }
}

これらの警告が生成されるのはなぜですか?

4

2 に答える 2

10

あなたのコードは、スローされた例外があなたのを閉じるステートメントをスキップする実行を引き起こす可能性を考慮に入れていますStringWriter。例外によって実行が終了する前にToCSV、を閉じるようにする必要がありswます。

これを処理する最も簡単な方法は、usingブロックを使用することです。句内に構築されたオブジェクトusingは、ブロックのスコープが終了する前に破棄されることが保証されています。

public string ToCsv()
{
    IEnumerable<string> props = GetProperties();
    using (StringWriter sw = new StringWriter())
    {
        sw.WriteLine(GetHeadings(props));
        WriteValues(props, sw);
        return sw.ToString();
    }
}

CloseDisposeStringWriterの両方を呼び出す必要はないことに注意してください。ちょうどDispose十分です。

using一般に、実装するすべてのオブジェクトの作成と使用の周りにブロックをラップする必要がありますIDisposableStringWriterそうするように)。これにより、どの例外がスローされても、オブジェクトは常に適切に破棄されます。

于 2010-09-23T23:38:14.333 に答える
3

2番目の警告は、StringWriter.Close()がStringWriter.Dispose()、http: //msdn.microsoft.com/en-us/library/system.io.stringwriter.close.aspxを呼び出すため、Disposeを2回呼び出しているためです。

最初の警告は、新しいStringWriter()の後に例外が発生した場合、Disposeを呼び出すcatchステートメントがないためです。コードを次のように書き直すことをお勧めします

using (StringWriter sw = new StringWriter()) { 
    sw.WriteLine(GetHeadings(props));
    WriteValues(props, sw);
    return sw.ToString();
}
于 2010-09-23T23:40:29.447 に答える