Лучшая практика для вложенных операторов?
У меня есть блок кода следующим образом, и я использую 3 вложенных блока using
.
Я обнаружил, что с помощью блоков try finally
я могу избежать этого, но если есть более двух операторов using, то какой лучший подход?
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");
}
}
}
Ответы
Ответ 1
Вы можете удалить отступ вложенности следующим образом:
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
}
Ответ 2
Немного менее подробный способ избежать отступов:
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");
}
Как указал Джон Скит, нет необходимости в том, чтобы эти переменные являлись переменными экземпляра, поскольку они расположены после блоков using
в любом случае.
Вместо этого вы можете использовать локальные переменные, как показано в приведенном выше коде.
Ответ 3
Может быть, что-то условное; лучший подход для выбора между двумя, на мой взгляд, будет:
-
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
}
Ответ 4
В одном методе, когда вам не нужно обрабатывать или изменять данные; выбор, предложенный Яном Соммером, был бы моим выбором. Однако в некоторых случаях одноразовый список полезен. В частности, если у вас много одноразовых полей, которые нужно удалить (в этом случае вы не можете использовать их).
Требуется, чтобы вы не добавили элемент в список. (Хотя вы могли бы также сказать, что вы должны не забывать использовать его.)
Прерывает процесс удаления, если один из методов размещения выдает, оставляя оставшиеся предметы неактивными.
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 после прохождения всех элементов. Я добавил вспомогательный метод Add, который позволяет более простое использование:
using (var disposables = new DisposableList())
{
var file = disposables.Add(() => File.Create("test"));
// ...
var memory = disposables.Add(() => new MemoryStream());
// ...
var cts = disposables.Add(() => new CancellationTokenSource());
// ...
}