12

I see the following code pattern all over the place in my company's codebase (.NET 3.5 application):

bool Foo(int barID, out Baz bazObject) { 
    try { 
            // do stuff
            bazObject = someResponseObject;

            return true;
    }
    catch (Exception ex) { 
        // log error
        return false;
    }
}

// calling code
BazObject baz = new BazObject();
fooObject.Foo(barID, out baz);

if (baz != null) { 
    // do stuff with baz
}

I'm trying to wrap my head around why you would do this instead of having the Foo method simply take the ID and return a Baz object, instead of returning a value that isn't used and having the actual object be a ref or output parameter.

Is there some hidden benefit of this coding style that I'm missing?

yannis
  • 39,647
Wayne Molina
  • 15,712

5 Answers5

12

You usually use that pattern so you can write code like this:

if (Foo(barId, out bazObject))
{
  //DoStuff with bazobject
}

it's used in the CLR for TryGetValue in the dictionary class for instance. It avoids some redundancy but out and ref parameters always seemed a bit messy to me

Homde
  • 11,114
11

This is old C style code, before there were exceptions. The return value indicated whether the method was successful or not, and if it was, the parameter would be filled with the result.

In .net we have exceptions for that purpose. There should be no reason to follow this pattern.

[edit] There are obviously performance implications in exception handling. Maybe that has something to do with it. However, in that code snippet there's already an exception being thrown. It would be cleaner to just let it move up the stack until it's caught in a more appropriate place.

2

Given the code snippet it looks completely pointless. To me the initial code pattern would suggest that null for BazObject would be an acceptable case and the bool return is a measure of determining a fail case safely. If the following code was:

// calling code
BazObject baz = new BazObject();
bool result = fooObject.Foo(barID, out baz);

if (result) { 
    // do stuff with baz
    // where baz may be 
    // null without a 
    // thrown exception
}

This would make more sense to me to do it this way. Perhaps this is a method someone before you was using to guarantee that baz was being passed by reference without understanding how object parameters actually work in C#.

Joel Etherton
  • 11,684
  • 7
  • 47
  • 55
1

Sometimes this pattern is useful when you, the caller, aren't supposed to care whether the returned type is a reference or value type. If you are calling such a method to retrieve a value type, that value type will either need an established invalid value (e.g. double.NaN), or you need some other way of determining success.

Kevin Hsu
  • 1,621
  • 10
  • 11
0

The idea is to return a value that indicates whether the process was successful, allowing code like this:

Baz b;
if (fooObject.foo(id, out b)) {
   // do something with b
}
else {
   Error.screamAndRun("object lookup/whatever failed! AAaAAAH!");
}

If the object cannot be null (which appears correct in your example), it's better done as follows:

Baz b = fooObject.foo(id);
if (b != null) {
   // do something with b
}
else {
   Error.screamAndRun("object lookup/whatever failed! AAaAAAH!");
}

If the object can be null, exceptions are the way to go:

try {
   Baz b = fooObject.foo(id);
}
catch (BazException e) {
   Error.screamAndRun("object lookup/whatever failed! AAaAAAH!");
}

It's a common pattern used in C, where there are no exceptions. It allows the function to return an error condition. Exceptions are generally a much cleaner solution.

Michael K
  • 15,659