简体   繁体   English

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

[英]How should I deal with null objects in a using block?

Given a situation like this: 鉴于这样的情况:

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

I would like to avoid the nested if. 我想避免嵌套if。 Sadly, the obvious solution is not possible because break does not work with using: 遗憾的是,显而易见的解决方案是不可能的,因为break不能用于:

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

Is there a pattern to still avoid the additional indentation caused by the if != null ? 是否有一种模式仍然可以避免由if != null引起的额外缩进?

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

I favor small clearly named methods: 我赞成小明确命名的方法:

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

     //DoWhatEver
   }
}

Introduce a helper method that takes a lambda. 介绍一个带lambda的辅助方法。 So your code becomes: 所以你的代码变成:

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

which has the indentation you want. 哪个有你想要的缩进。 The definition of UsingIfNotNull is: UsingIfNotNull的定义是:

public static void UsingIfNotNull<T>(T item, Action<T> action) where T : class, IDisposable {
  if(item!=null) {
    using(item) {
      action(item);
    }
  }
}

This is just a style issue ... code is fine. 这只是一个样式问题......代码很好。 Are you really that worried about indents? 你真的担心缩进吗? Here's another way to lose the indents anyway ... 这是另一种失去缩进的方法......

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

}

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

    //DoWhatEver

}

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

It's an ugly hack, but it avoids the additional identation: 这是一个丑陋的黑客,但它避免了额外的身份:

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

(No, I don't recommend to do this. This is just a proof-of-concept to show that it's possible.) (不,我不建议这样做。这只是一个概念验证,表明它是可能的。)

If possible, I would suggest to refactor your code instead: 如果可能的话,我建议改为重构你的代码:

 using (var foo = CreateFoo()) {
    if (foo != null) {
        doSomethingWith(foo);  // only one line highly indented
    }
}

Personally I would probably leave the code as you've posted it. 就个人而言,我可能会在您发布代码时留下代码。

However, since you asked (and at the risk of exposing myself to downvotes to this often-maligned language feature), you could always use "goto": 但是,既然你问过(并且有可能让自己暴露于这种经常被诽谤的语言特征),你可以随时使用“goto”:

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

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

C# compiler treats using(var foo = CreateFoo()) statement in: C#编译器使用(var foo = CreateFoo())语句处理:

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

If your method CreateFoo return not disposable object - do not use using at all. 如果您的方法CreateFoo返回不是一次性对象 - 请勿使用。 In other case you can write: 在其他情况下,你可以写:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM