我应该如何处理使用块中的空对象?

时间:2011-09-22 12:55:55

标签: c# .net using code-readability

考虑到这样的情况:

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

我想避免嵌套if。遗憾的是,显而易见的解决方案是不可能的,因为break不能使用:

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

是否还有一种模式可以避免if != null引起的额外缩进?

8 个答案:

答案 0 :(得分:6)

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

答案 1 :(得分:3)

我赞成小的明确命名的方法:

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

     //DoWhatEver
   }
}

答案 2 :(得分: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);
    }
  }
}

答案 3 :(得分:1)

这只是一个样式问题......代码很好。你真的担心缩进吗?这是另一种失去缩进的方法......

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

}

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

    //DoWhatEver

}

答案 4 :(得分:0)

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

答案 5 :(得分: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
    }
}

答案 6 :(得分:0)

我个人可能会在你发布代码时留下代码。

然而,既然你问过(并且冒着让自己暴露于这种经常被诽谤的语言特征)的风险,你可以随时使用“转到”:

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

SkipUsingBlock:
// the rest of the code...

答案 7 :(得分:0)

C#编译器使用(var foo = CreateFoo())语句处理:

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

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

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();
}