4

鉴于这样的情况:

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

我想避免嵌套的 if。可悲的是,明显的解决方案是不可能的,因为 break 不适用于使用:

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

是否有一种模式仍然可以避免由if != null?

4

8 回答 8

6

如果您对从返回的类有足够的控制权,则CreateFoo()可以实现一个Null 对象并返回它而不是实际的 NULL 值

于 2011-09-22T13:06:59.683 回答
3

我喜欢小的明确命名的方法:

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

     //DoWhatEver
   }
}
于 2011-09-22T13:01:12.990 回答
3

引入一个采用 lambda 的辅助方法。所以你的代码变成:

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);
    }
  }
}
于 2011-09-22T13:58:35.973 回答
1

这只是一个风格问题......代码很好。你真的那么担心缩进吗?无论如何,这是另一种丢失缩进的方法......

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

}

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

    //DoWhatEver

}
于 2011-09-22T13:12:04.563 回答
0

在那种一般意义上,我相信我会将 using 包装在一个try...catch块中并在对象为空时抛出异常,但这是个人喜好。

于 2011-09-22T12:59:05.160 回答
0

这是一个丑陋的黑客,但它避免了额外的标识:

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
    }
}
于 2011-09-22T13:01:08.040 回答
0

就我个人而言,我可能会保留您发布的代码。

然而,既然你问了(并且冒着让自己对这个经常被诽谤的语言功能投反对票的风险),你总是可以使用“goto”:

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

SkipUsingBlock:
// the rest of the code...
于 2011-09-22T13:06:02.533 回答
0

C# 编译器将 using(var foo = CreateFoo()) 语句处理为:

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

如果您的方法 CreateFoo 返回不是一次性对象 - 根本不要使用 using。在其他情况下,您可以编写:

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();
}
于 2011-09-22T13:18:25.853 回答