嵌套使用语句的最佳实践?

时间:2014-04-21 12:37:33

标签: c# .net using-statement

我有一个代码块如下,我使用3个嵌套using块。

我发现使用try finally块我可以避免这种情况,但如果有两个以上的使用语句,那么最好的方法是什么?

private FileStream fileStream = null;
private Document document = null;
private PdfWriter pdfWriter =  null;

using (fileStream = new FileStream("ABC.pdf", FileMode.Create))
{
    using (document = new Document(PageSize.A4, marginLeft, marginRight, marginTop, marginBottom))
    {
        using (pdfWriter = PdfWriter.GetInstance(document, fileStream))
        {
            document.AddAuthor(metaInformation["author"]);
            document.AddCreator(metaInformation["creator"]);
            document.AddKeywords("Report Generation using I Text");
            document.AddSubject("Document subject");
            document.AddTitle("The document title");
        }
    }
}

5 个答案:

答案 0 :(得分:11)

您可以通过以下方式删除嵌套缩进:

using (var fileStream = new FileStream("ABC.pdf", FileMode.Create))
using (var document = new Document(PageSize.A4, marginLeft, marginRight, marginTop, marginBottom))
using (var pdfWriter = PdfWriter.GetInstance(document, fileStream))
{
   // code
}

答案 1 :(得分:4)

避免缩进的一种不那么冗长的方式:

  using (var fileStream = new FileStream("ABC.pdf", FileMode.Create))
  using (var document = new Document(PageSize.A4, marginLeft, marginRight, marginTop, marginBottom))
  using (var pdfWriter = PdfWriter.GetInstance(document, fileStream))
  {
       document.AddAuthor(metaInformation["author"]);
       document.AddCreator(metaInformation["creator"]);
       document.AddKeywords("Report Generation using I Text");
       document.AddSubject("Document subject - Describing the steps creating a PDF document");
       document.AddTitle("The document title - PDF creation using iTextSharp");
   }

正如Jon Skeet指出的那样,这些变量不需要是实例变量,因为它们无论如何都会被置于using块之后。

您可以使用上面代码中显示的局部变量。

答案 2 :(得分:2)

也许传统;在我看来中选择两个的最佳方法是

  • Using:如果您要在上下文中使用某个实例,并在完成后需要Dispose
  • try/finally:如果您预计遇到任何问题并与例外有关,请在Dispose您正在使用的实例之前将其捕获。

正如其他评论/答案所述;你不需要实例级变量;

using (FileStream fileStream = new FileStream("ABC.pdf", FileMode.Create))
using (Document document = new Document(PageSize.A4, marginLeft, marginRight, marginTop, marginBottom))
using (PdfWriter pdfWriter = PdfWriter.GetInstance(document, fileStream))
{
    // # Implementation here seems like a good approach
}

答案 3 :(得分:0)

在单一方法中,您不需要处理或更改数据; Jan Sommer建议的选项将是我的选择。但是,在某些情况下,DisposableList很有用。特别是,如果您有许多需要处理的一次性场地(在这种情况下您不能使用)。

要求您记住将项目添加到列表中。 (虽然你也可以说你必须记得使用。) 如果其中一种处置方法抛出,则中止处理过程,剩下的物品不予处置。

public class DisposableList : List<IDisposable>, IDisposable
{
    public void Dispose()
    {
        if (this.Count > 0)
        {
            List<Exception> exceptions = new List<Exception>();

            foreach (var disposable in this)
            {
                try
                {
                    disposable.Dispose();
                }
                catch (Exception e)
                {
                    exceptions.Add(e);
                }
            }
            base.Clear();

            if (exceptions.Count > 0)
                throw new AggregateException(exceptions);
        }
    }

    public T Add<T>(Func<T> factory) where T : IDisposable
    {
        var item = factory();
        base.Add(item);
        return item;
    }
}

现在从Dispose调用中捕获任何异常,并在遍历所有项目后抛出新的AggregateException。我添加了一个帮助器添加方法,允许更简单的使用:

using (var disposables = new DisposableList())
{
        var file = disposables.Add(() => File.Create("test"));
        // ...
        var memory = disposables.Add(() => new MemoryStream());
        // ...
        var cts = disposables.Add(() => new CancellationTokenSource());
        // ... 
}

答案 4 :(得分:0)

现在在C#8上,您有using declarations

    using var fileStream = new FileStream("ABC.pdf", FileMode.Create);
    using var document = new Document(PageSize.A4, marginLeft, marginRight, marginTop, marginBottom);
    using var pdfWriter = PdfWriter.GetInstance(this.document, this.fileStream);