Checking whether the type is a tuple (ValueTuple)
Continuing with my tuples (ValueTuple<...>
to be precise) exploration in C# I was in a need to check whether the type is a “tuple”. The (T, T, T, ...)
in C#. You can create ValueTuple<...>
yourself manually, but you can also create something that’s not a tuple – compiler wouldn’t do it that way.
For example ValueTuple<int, int, int, int, int, int, int, int>
compiles fine, but the 8th element (TRest
) should be another ValueTuple<int>
. Similarly also plain int
isn’t a tuple, obviously.
So I wrote a small helper for myself.
public static bool IsTuple(Type tuple)
{
if (!tuple.IsGenericType)
return false;
var openType = tuple.GetGenericTypeDefinition();
return openType == typeof(ValueTuple<>)
|| openType == typeof(ValueTuple<,>)
|| openType == typeof(ValueTuple<,,>)
|| openType == typeof(ValueTuple<,,,>)
|| openType == typeof(ValueTuple<,,,,>)
|| openType == typeof(ValueTuple<,,,,,>)
|| openType == typeof(ValueTuple<,,,,,,>)
|| (openType == typeof(ValueTuple<,,,,,,,>) && IsTuple(tuple.GetGenericArguments()[7]));
}
To be touch bit sure it works as it should, here’s some tests (using NUnit).
[TestCase(typeof((int, int)), ExpectedResult = true)]
[TestCase(typeof((int, int, string, string, int, int, string, string, int, int)), ExpectedResult = true)]
[TestCase(typeof(int), ExpectedResult = false)]
[TestCase(typeof(ValueTuple<int, int, int, int, int, int, int, int>), ExpectedResult = false)]
[TestCase(typeof(ValueTuple<int, int, int, int, int, int, int, ValueTuple<string, string>>), ExpectedResult = true)]
public bool IsTupleTest(Type tuple)
{
return TupleHelper.IsTuple(tuple);
}
There’s one small catch, though. You can’t really create a ValueTuple<T>
(on a top level) using C# (T)
syntax, because for the compiler the (
and )
are just plain parentheses, but I consider that for me as a valid tuple anyway.