2013-09-02 8 views
2

У меня очень простой механизм ведения журнала в моем приложении, который периодически записывает строку в файл (библиотека журналов будет излишней для моих нужд), которая выглядит примерно так:Использование инструкции using с уже созданным объектом

private string logfile = @"C:\whatever.log"; 

public void WriteLine(string line) 
{ 
    using(FileStream fs = File.Open(logfile, FileMode.Append)) 
    { 
    // Log Stuff 
    } 
} 

Таким образом, в любое время, когда я вызываю этот метод, новый FileStream создается и удаляется после завершения регистрации. Поэтому я рассматривал возможность использования уже экземпляр объекта, чтобы предотвратить непрерывное создание новых объектов:

private string logfile = @"C:\whatever.log"; 
private FileStream myStream = File.Open(logfile, FileMode.Append); 

public void WriteLine(string line) 
{ 
    using(myStream) 
    { 
    // Log Stuff 
    } 
} 

Однако the MSDN reference discourages this (последний пример), из-за проблемы области видимости. Что делать в этом случае? Является ли накладные расходы в моем первом примере незначительными?

+4

Micro-оптимизации?Сначала измерьте ... –

+2

Вы понимаете, почему вторая идея - это не просто то, что должно быть обескуражено, но плоская работа не работает? Рассматривали ли вы просто использование 'File.AppendText', чтобы сделать вещи проще? (и это все в дополнение к точке Митча, что, возможно, даже не стоит заботиться о ней в первую очередь). – Chris

+1

Вы знаете, что 'using' использует поток? Итак, после первого вызова «WriteLine», поток будет удален и больше не будет использоваться. –

ответ

3

using заявление больше ничего не делать, чем вызов метода Dispose() объекта.
Так что, учитывая ваш второй пример, после первого вызова метода WriteLine(string) фильтр расположен. Таким образом, любой другой вызов, после первого, к этому методу приведет к исключению.

Использование метода File.AppendText(), например, предложенного Крисом в комментариях, является способом выхода. Но имейте в виду, что использование этого или любого другого метода File... также откроет поток и закроет его после этого.
Это приведет к уменьшению количества кода.

1

Накладные расходы могут быть незначительными, но это может быть около точки.

Когда вы используете using, создание, приобретение ресурса и утилизация использованных ресурсов в значительной степени ограничены. Вы знаете, где он начинается, где он используется и где он закончен.

Если вы идете по второму сценарию, вы знаете, где он начинается (это когда создается класс-созерцатель), но после этого у вас нет гарантированного платформой способа контроля, где он используется, и где (если вообще) ресурсы располагаются.

Вы можете сделать это самостоятельно, если это критический код, и ваш содержащий класс реализует IDisposable pattern правильно, но это может быть сложно и не для слабонервных :)

Однако, вы заявили в вопросе " библиотека журналов будет излишней для моих нужд », поэтому я думаю, что у вас все в порядке с минимальными издержками. ИМХО, вы должны быть хорошо с одним из готовых File методов, как File.AppendAllText:

public void WriteLine(string line) 
{ 
    //add an enter to the end 
    line += Environment.NewLine; 
    File.AppendAllText(logfile, line); 
} 

или File.AppendAllLines:

public void WriteLine(string line) 
{ 
    File.AppendAllLines(logfile, new []{line}); 
} 
2

Второй подход также уничтожает поток каждый раз, когда вы вызываете WriteLine, так как вы также используете код using. MSDN отказывается от этого подхода, потому что переменная myStream все еще существует, даже если объект удален. Так что это более подвержено ошибкам.

Если вам часто нужно использовать этот метод, вы должны cosider использовать using «снаружи» или использовать try-catch-finally:

var myLogger = new MyLogger(); 
try 
{  
    // here is your app which calls myLogger.WriteLine(...) often 
} 
catch(Exception ex) 
{ 
    // log it 
} 
finally 
{ 
    myLogger.Dispose(); // myLogger is your Log class, dispose should call myStream.Dispose(); 
} 
Смежные вопросы