views:

752

answers:

16

I'm just wondering how other developers tackle this issue of getting 2 or 3 answers from a method.

1) return a object[]
2) return a custom class
3) use an out or ref keyword on multiple variables
4) write or borrow (F#) a simple Tuple<> generic class
http://slideguitarist.blogspot.com/2008/02/whats-f-tuple.html

I'm working on some code now that does data refreshes. From the method that does the refresh I would like to pass back (1) Refresh Start Time and (2) Refresh End Time.
At a later date I may want to pass back a third value.

Thoughts? Any good practices from open source .NET projects on this topic?

+10  A: 

For two, usually 4)

More than that, 2)

James Curran
Doesn't help yet, but .NET 4.0 will include a generic Tuple class in the BCL.
Scott Dorman
Sounds like a typical Microsoft solution - add yet another obscure feature.
le dorfier
Obscure? People have been asking for Tuples and Multiple Return Values since version 1.
Jonathan Allen
+1  A: 

I use out if it's only 1 or 2 additional variables (for example, a function returns a bool that is the actual important result, but also a long as an out parameter to return how long the function ran, for logging purposes).

For anything more complicated, i usually create a custom struct/class.

Michael Stum
+1  A: 

I think the most common way a C# programmer would do this would be to wrap the items you want to return in a separate class. This would provide you with the most flexibility going forward, IMHO.

Brian Sullivan
+27  A: 

It entirely depends on what the results are. If they are related to one another, I'd usually create a custom class.

If they're not really related, I'd either use an out parameter or split the method up. If a method wants to return three unrelated items, it's probably doing too much. The exception to this is when you're talking across a web-service boundary or something else where a "purer" API may be too chatty.

Jon Skeet
+1 Agree on this. Methods which return > 2 different things propably do way too much
drax
>1 unrelated things anyway, big fan of class i/o for methods +1
annakata
99% of the time you want to make a custom struct, not a class, but +1 anyways
Matt Briggs
@Google Ninja: No, I don't believe you usually *do* want a custom struct. I find that custom structs are *very* rarely appropriate.
Jon Skeet
I normally agree, but I sometimes (seldom) group functions that return two unrelated items, but get them from a rather expensive operation that i only want to run once.
Michael Stum
That sounds similar to my last sentence - not exactly the same, but along the same lines. Where possible it's nice to extract the bits out, of course, but you do need to be pragmatic.
Jon Skeet
+1  A: 

It depends. For an internal only API, I'll usually choose the easiest option. Generally that's out.

For a public API, a custom class usually makes more sense - but if it's something fairly primitive, or the natural result of the function is a boolean (like *.TryParse) I'll stick with an out param. You can do a custom class with an implicit cast to bool as well, but that's usually just weird.

For your particular situation, a simple immutable DateRange class seems most appropriate to me. You can easily add that new value without disturbing existing users.

Mark Brackett
+2  A: 

Code Architeture wise i'd always go with a Custom Class when needing somewhat a specific amount of variables changed. Why? Simply because a Class is actually a "blueprint" of an often used data type, creating your own data type, which it in this case is, will help you getting a good structure and helping others programme for your interface.

Filip Ekberg
A: 

If 2, a Pair.

If more than 2 a class.

John MacIntyre
Never noticed the System.Web.UI.Pair class. Guess you would just use the Tuples coming in VS2010 moving forward.
tyndall
+4  A: 

Your question points to the possibility that you'll be returning more data in the future, so I would recommend implementing your own class to contain the data.

What this means is that your method signature will remain the same even if the inner representation of the object you're passing around changes to accommodate more data. It's also good practice for readability and encapsulation reasons.

Dave R.
+1 Good point about future needs. By using a class you can add to the class without changing the method or the caller.
tyndall
+1  A: 

If you're wanting to send back the refresh start and end times, that suggests a possible class or struct, perhaps called DataRefreshResults. If your possible third value is also related to the refresh, then it could be added. Remember, a struct is always passed by value, so it's allocated on the heap does not need to be garbage-collected.

Frank Ames
+2  A: 

Personally, I hate out/ref params, so I'd rather not use that approach. Also, most of the time, if you need to return more than one result, you are probably doing something wrong.

If it really is unavoidable, you will probably be happiest in the long run writing a custom class. Returning an array is tempting as it is easy and effective in the short teerm, but using a class gives you the option of changing the return type in the future without having to worry to much about causing problems down stream. Imagine the potential for a debugging nightmare if someone swaps the order of two elements in the array that is returned....

rotard
A: 

Another solution is to return a dictionary of named object references. To me, this is pretty equivalent to using a custom return class, but without the clutter. (And using RTTI and reflection it is just as typesafe as any other solution, albeit dynamically so.)

Jeff Kotula
Anything you do in the CLR is dynamically typesafe, so that isn't saying much!
Daniel Earwicker
+1  A: 

Some people use KeyValuePair for two values. It's not great though because it just labels the two things as Key and Value. Not very descriptive. Also it would seriously benefit from having this added:

public static class KeyValuePair
{
    public static KeyValuePair<K, V> Make(K k, V v) 
    { 
        return new KeyValuePair<K, V>(k, v); 
    }
}

Saves you from having to specify the types when you create one. Generic methods can infer types, generic class constructors can't.

Daniel Earwicker
+1  A: 

For your scenario you may want to define generic Range{T} class (with checks for the range validity).

If method is private, then I usually use tuples from my helper library. Public or protected methods generally always deserve separate.

Rinat Abdullin
+1  A: 

Return a custom type, but don't use a class, use a struct - no memory allocation/garbage collection overhead means no downsides.

Mike Scott
A: 

It depends on the type and meaning of the results, as well as whether the method is private or not.

For private methods, I usually just use a Tuple, from my class library.

For public/protected/internal methods (ie. not private), I use either out parameter or a custom class.

For instance, if I'm implementing the TryXYZ pattern, where you have an XYZ method that throws an exception on failure and a TryXYZ method that returns Boolean, TryXYZ will use an out parameter.

If the results are sequence-oriented (ie. return 3 customers that should be processed) then I will typically return some kind of collection.

Other than that I usually just use a custom class.

Lasse V. Karlsen
A: 

If a method outputs two to three related value, I would group them in a type. If the values are unrelated, the method is most likely doing way too much and I would refactor it into a number of simpler methods.

Brian Rasmussen