views:

495

answers:

5

I am almost embarrassed to ask this question, but as a long time C programmer I feel that perhaps I am not aware of the best way to do this in C#.

I have a member function that I need to return two lists of a custom type (List<MyType>) and I know beforehand that I will always have a return value of only two of these lists.

The obvious options are :

public List<List<MyType>> ReturnTwoLists();

or

public void ReturnTwoLists(ref List<MyType> listOne, ref List<myType> listTwo);

Both seem to be non-optimal.

Any suggestions on how to improve this?

The first way doesn't make it clear in the syntax that only 2 lists are being returned, and the second uses references rather then a return value, which seem so non-c#.

+14  A: 

Return this:

public class MyTwoLists {
    public List<MyType> ListOne {get;set;}
    public List<MyType> ListTwo {get;set;}
}
John Saunders
+20  A: 

First of all, that should probably be out, not ref.

Second, you can declare and return a type containing the two lists.

Third, you can declare a generic Tuple and return an instance of that:

class Tuple<T,U> {
   public Tuple(T first, U second) { 
       First = first;
       Second = second;
   }
   public T First { get; private set; }
   public U Second { get; private set; }
}

static class Tuple {
   // The following method is declared to take advantage of
   // compiler type inference features and let us not specify
   // the type parameters manually.
   public static Tuple<T,U> Create<T,U>(T first, U second) {
        return new Tuple<T,U>(first, second);
   }
}

return Tuple.Create(firstList, secondList);

You can extend this idea for different number of items.

Mehrdad Afshari
Just a remainder... .NET 4.0 has Tuple<> type.
guardi
I see that you used T and U to specify the items. If you had more than a 2-tuple, would you go for T-U-V-W... or T-U-P-L-E? :)
Mark Rushakoff
@Mark: haven't thought of it. Before I think about that, I'd think about switching to F#!
Mehrdad Afshari
A: 

Create a simple Structure that holds both and return that as the output of the function?

Ryan ONeill
+4  A: 

You're first suggestion isn't two lists. It's a list of lists. The second option would do what you intend, but you might want to change it to out instead of ref so the callers of your method will know the intention of what you're doing.

public void ReturnTwoLists(out List<MyType> listOne, out List<myType> listTwo);
Joseph
+1  A: 

You have a few options:

use a Pair if the lists are meaningless in order:

 public Pair<List<MyType>,List<MyType> ReturnTwoLists()
 {
        return new Pair(new List<MyType(), new List<MyType());
 }

You can use out or ref parameters, as you mentioned. This is a good option if one list is more meaningful than the other.

You could use a dictionary if the client will know the keys, or wants to do the work to look them up:

 public Dictionary<string,List<MyType> ReturnTwoLists()
 {
        Dictionary<string,List<MyTpe>> d = new Dictionary<string,List<MyType>>();
        d.Add("FirstList",new List<MyType>());
        d.Add("SecondList",new List<MyType>());
        return new Dictionary()(new List<MyType(), new List<MyType());
 }

Or, the most "correct" solution in my eyes, for completeness and consistency, would be to create a simple data container class to hold the two lists. This provides a consumer with strongly-typed, good statically compiled (read: intellisense-enabled) return values to work with. The class can be nested right next to the method.

JoshJordan