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();
}
精彩评论