Вопрос стиля/удобочитаемости относительно оператора “использования” C#

Я хотел бы знать Ваше мнение о вопросе стиля кодирования, что я нахожусь на заборе о. Я понимаю там, вероятно, не категорический ответ, но я хотел бы видеть, существует ли решительное предпочтение в одном направлении или другом.

Я прохожу добавление решения using операторы в довольно многих местах. Часто я буду сталкиваться с чем-то как так:

{
    log = new log();
    log.SomeProperty = something;  // several of these
    log.Connection = new OracleConnection("...");
    log.InsertData(); // this is where log.Connection will be used
    ... // do other stuff with log, but connection won't be used again
}

где журнал. Соединением является OracleConnection, который реализует IDisposable.

neatnik во мне хочет изменить его на:

{
    using (OracleConnection connection = new OracleConnection("..."))
    {
        log = new log();
        log.SomeProperty = something;
        log.Connection = conn;
        log.InsertData();
        ...
    }
}

Но любитель краткости и getting-the-job-done-slightly-faster хочет сделать:

{
    log = new log();
    log.SomeProperty = something; 
    using (log.Connection = new OracleConnection("..."))
        log.InsertData();
    ...
}

По некоторым причинам я чувствую себя немного грязным, делая это. Вы рассматриваете это плохо или нет? Если Вы думаете, что это плохо, почему? Если это хорошо, почему?

Править: Обратите внимание на то, что это - всего одно (несколько изобретенный) пример многих. Не фиксируйте на том, что это, оказывается, указывает на класс регистратора с плохо продуманным интерфейсом. Это не относится к моему вопросу, и я не имею право улучшать сами классы так или иначе.

7
задан Igby Largeman 21 May 2010 в 23:49
поделиться

5 ответов

Я согласен, что в идеале log сам должен реализовать IDisposable, но давайте предположим, что это невозможно, и обратимся к вопросу, который задал ОП.

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

Также обратите внимание, что вы можете выполнить другую инициализацию вне блока using. Здесь это не имеет значения, но может иметь значение, если вы "используете" какой-то очень дорогой ресурс. То есть:

log = new log();
log.SomeProperty = something; // This can be outside the "using"
using (OracleConnection connection = new OracleConnection("..."))
{
    log.Connection = conn;
    log.InsertData();
    ...
}
2
ответ дан 7 December 2019 в 01:17
поделиться

Эти два способа использования using абсолютно эквивалентны. В любом случае вы получите журнал, который все еще находится в области видимости, но имеет удаленное соединение. Гораздо лучше сделать журнал одноразовым и заставить его метод dispose утилизировать соединение, поместив журнал в оператор using, а не само соединение.

1
ответ дан 7 December 2019 в 01:17
поделиться

Они оба ужасны. Не делайте ни того, ни другого.

Вы делаете здесь то, что я называю " классом высокого обслуживания ". У класса с высоким уровнем обслуживания есть контракт, в котором говорится: «Я требую, чтобы вы предоставили мне кучу ресурсов, и вы должны знать, когда я закончу с ними, и очистить их соответствующим образом». Этот контракт означает, что пользователь класса должен знать, как этот класс реализован, тем самым нарушая принцип инкапсуляции и абстракции, который изначально мотивировал создание класса.

Вы можете сказать это по вашему комментарию: здесь используется соединение, я знаю, что соединение больше не будет использоваться . Откуда ты это знаешь? Вы знаете только это, если это задокументированный контракт класса . Это не лучший контракт, чтобы навязывать его потребителю класса.

Некоторые способы сделать это лучше:

1) сделать регистратор одноразовым. Попросите его очистить соединение, когда это будет сделано. Обратной стороной этого является то, что регистратор удерживает соединение дольше, чем необходимо.

2) заставить InsertData принимать соединение как параметр. Вызывающий по-прежнему может нести ответственность за очистку соединения, потому что регистратор не удерживает его.

3) создайте третий класс «Inserter», который является одноразовым и принимает журнал и соединение в своем конструкторе. Устройство для вставки избавляется от соединения, когда оно удаляется; тогда вызывающий абонент отвечает за утилизацию устройства вставки.

5
ответ дан 7 December 2019 в 01:17
поделиться

Если log реализует IDisposable, то сделайте второй вариант, так как скобки являются явными. В некоторых случаях можно использовать несколько утверждений using:

using (Graphics g = ...)
using (Pen p = new Pen ...)
using (Font f = new Font ...)
{



}

где можно обойтись только одним набором скобок. Это позволяет избежать безумных отступов.

0
ответ дан 7 December 2019 в 01:17
поделиться

Я бы послушал аккуратного в вас. Лично мне его путь больше нравится.

2
ответ дан 7 December 2019 в 01:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: