# I've started Tuples to LINQ and I'm not sure if it's an anti pattern

I have

public static class TupleExtensions {

public static IEnumerable<T> SelectMany<T>(this IEnumerable<Tuple<T, T>> te)
{
foreach (var t in te)
{
yield return t.Item1;
yield return t.Item2;
}
}

public static IEnumerable<T> SelectMany<T, U>(this IEnumerable<U> source, Func<U, Tuple<T, T>> fn)
{
foreach (var s in source)
{
var t = fn(s);
yield return t.Item1;
yield return t.Item2;
}

}

public static IEnumerable<T> SelectMany<T, U>(this IEnumerable<U> source, Func<U, Tuple<T, T, T>> fn)
{
foreach (var s in source)
{
var t = fn(s);
yield return t.Item1;
yield return t.Item2;
yield return t.Item3;
}

}

public static IEnumerable<T> SelectMany<T, U>(this IEnumerable<U> source, Func<U, Tuple<T, T, T,T>> fn)
{
foreach (var s in source)
{
var t = fn(s);
yield return t.Item1;
yield return t.Item2;
yield return t.Item3;
yield return t.Item4;
}

}
}


I can then do as a trivial example

IEnumerable<int> source = ...
source.SelectMany(i=>Tuple.Create(i, i+1, i+2))


Obviously the tuple must have the same types throughout. My use case is where I have a mathematical solver which will always return two solutions for a given input. Returning a list makes it unclear how many solutions would be returned.

However in the end I would want all my solutions merged. For example

static Tuple<Point,Point> Intersect(this Shape shape, Line other);

Shape shape = ...
IEnumerable<Line> lines = ...

IEnumerable<Point> intersections = lines.SelectMany(line=>shape.Intersect(line));


Is there some good reason not to treat Tuple<T,T,T....> as a container that we can flatten?

• I'd rather use collections (perhaps immutable, perhaps simple arrays). Jun 20, 2013 at 9:58
• No, there's no good reason not to consider tuples this way. If it seems "wrong" somehow, it's only because C# has such limited support for tuples. In a functional language, or one with better tuple support, this would seem very natural. Jun 20, 2013 at 10:00
• @CodesInChaos the problem with collections is that the length is not considered part of the type. If my function should always return two values but I return a List<Point> should the client of that code put in a check that there are in fact two values or risk an index out of bounds exception? Jun 20, 2013 at 10:06
• if you really want length to be part of the type, then create a custom type. Else simply go with T[] or ReadOnlyCollection<T>. Jun 20, 2013 at 10:10
• @CodesInChaos Can you explain why you think Tuple is wrong for this? In C++ I could create a type with an integer type parameter with a recursive template definition. In C# that is not possible. How would you make a generic Container<T,length> type other than with Tuple? Jun 20, 2013 at 10:58

In general, I think this pattern makes sense, because it clearly expresses what the method returns and lets you easily do the computation you want to do with the result.

Some thoughts:

1. I don't see any reason why your extension methods should only work on a collection of Tuples and not on a single Tuple. Because of that, I would probably write extension methods that convert a single Tuple to IEnumerable:

public static IEnumerable<T> ToEnumerable<T>(this Tuple<T, T> tuple)
{
yield return tuple.Item1;
yield return tuple.Item2;
}


Since this would make the code you showed more complicated, it might make sense to also keep SelectMany(), but express it using ToEnumerable():

public static IEnumerable<T> SelectMany<T>(
this IEnumerable<Tuple<T, T>> tuples)
{
return tuples.SelectMany(t => t.ToEnumerable());
}

public static IEnumerable<T> SelectMany<T, U>(
this IEnumerable<U> source, Func<U, Tuple<T, T>> selector)
{
return source.SelectMany(x => selector(x).ToEnumerable());
}

2. It might make sense to create custom types that mean “pair (triple, …) of items of the same type”. As a side benefit, you wouldn't need custom ToEnumerable() or SelectMany() extensions, since those types could implement IEnumerable<T> directly.

• I like this. Shame that we can't create an implicit cast to IEnumerable<T> and all this would work automagically. Jun 20, 2013 at 11:35
• Isn't all you need ToEnumerable? IEnumerable<Point> intersections = lines.SelectMany(line=>shape.Intersect(line).ToEnumerable()); looks all right to me. What does all the rest give? Jun 20, 2013 at 13:32
• @abuzittingillifirca Yes, that works fine, but I think an overload of SelectMany() makes sense to make the code shorter, especially since the Tuple can be considered a sequence, so the SelectMany() does logically make sense. Jun 20, 2013 at 13:54
• @bradgonesurfing To be consistent with existing LINQ APIs you should use the semantics AsEnumerable instead of ToEnumerable : msdn.microsoft.com/en-us/library/bb335435.aspx , msdn.microsoft.com/en-us/library/…, stackoverflow.com/questions/9873930/… , Aug 30, 2013 at 18:15