开发者

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. Sadly, the obvious solution is not possible because break does not work with using:

using (var foo = CreateFoo()) {
    if (foo开发者_Python百科 == null) {
        break;
    }
    // do stuff
}

Is there a pattern to still avoid the additional indentation caused by the if != null?


If you have sufficient control over the class returned from CreateFoo() you could just implement a Null Object and return this instead of the actual NULL value


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. So your code becomes:

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

which has the indentation you want. The definition of UsingIfNotNull is:

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

}


In that sort of generic sense, I believe I would wrap the using in a try...catch block and throw an exception if the object was null, but that's a personal preference.


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":

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

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


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
    }
}


C# compiler treats using(var foo = CreateFoo()) statement in:

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

If your method CreateFoo return not disposable object - do not use using at all. 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();
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜