Как я должен иметь дело с нулевыми объектами в блоке использования? - PullRequest
3 голосов
/ 22 сентября 2011

Учитывая ситуацию, подобную этой:

using (var foo = CreateFoo()) {
    if (foo != null) {
        // do stuff
    }
}

Я бы хотел избежать вложенного if. К сожалению, очевидное решение невозможно, потому что break не работает с использованием:

using (var foo = CreateFoo()) {
    if (foo == null) {
        break;
    }
    // do stuff
}

Существует ли шаблон, позволяющий избежать дополнительного отступа, вызванного if != null?

Ответы [ 8 ]

6 голосов
/ 22 сентября 2011

Если у вас есть достаточный контроль над классом, возвращаемым из CreateFoo(), вы можете просто реализовать Null Object и вернуть его вместо фактического значения NULL

3 голосов
/ 22 сентября 2011

Введите вспомогательный метод, который принимает лямбду.Таким образом, ваш код становится:

UsingIfNotNull(CreateFoo(), foo => {
  //do stuff
});

с нужным отступом.Определение UsingIfNotNull:

public static void UsingIfNotNull<T>(T item, Action<T> action) where T : class, IDisposable {
  if(item!=null) {
    using(item) {
      action(item);
    }
  }
}
3 голосов
/ 22 сентября 2011

Я предпочитаю маленькие четко названные методы:

public void DoWhatEver()
{
   using (var foo = CreateFoo())
   {
     if (foo == null) return;

     //DoWhatEver
   }
}
1 голос
/ 22 сентября 2011

Это просто проблема стиля ... код в порядке.Вы действительно беспокоитесь о отступах?Вот еще один способ потерять отступы в любом случае ...

public void DoWhatEver()
{
   using(var foo = CreateFoo())
   {
       DoStuffWithFoo(foo);
   }

}

private void DoStuffWithFoo(Foo foo)
{
    if(foo == null) return;

    //DoWhatEver

}
0 голосов
/ 22 сентября 2011

Компилятор C # обрабатывает с помощью оператора (var foo = CreateFoo ()) в:

try
{
var foo = CreateFoo();
}
finally
{
  ((IDisposable) foo).Dispose();
}

Если ваш метод CreateFoo возвращает не одноразовый объект - не используйте use вообще.В другом случае вы можете написать:

try
{
var foo = CreateFoo();
//do stuff like foo.SomeMethod (if foo == null exception will be thrown and stuff will not be done)
}
finally
{
  ((IDisposable) foo).Dispose();
}
0 голосов
/ 22 сентября 2011

Лично я бы, вероятно, оставил код, как вы его опубликовали.

Однако, так как вы спросили (и рискуете подвергнуться негативным последствиям этой часто порочащейся языковой функции), вы всегда можете использовать «goto»:

using (var foo = CreateFoo()) {
    if (foo == null) {
        goto SkipUsingBlock;
    }
    // do stuff
}

SkipUsingBlock:
// the rest of the code...
0 голосов
/ 22 сентября 2011

Это уродливый хак, но он избегает дополнительной идентификации:

do using (var foo = CreateFoo()) {
    if (foo == null) {
        break;
    }
    // do stuff
} while (false);

(Нет, я не рекомендую делать это. Это просто подтверждение концепции, чтобы показать, что это возможно.)

Если возможно, я бы предложил вместо этого изменить код:

 using (var foo = CreateFoo()) {
    if (foo != null) {
        doSomethingWith(foo);  // only one line highly indented
    }
}
0 голосов
/ 22 сентября 2011

В этом родовом смысле, я полагаю, что я обернул бы использование в блок try...catch и выбросил бы исключение, если объект был нулевым, но это личное предпочтение.

...