1

I'm trying to make use of ValueTuple to concisely enter a list of N types in a generic method's parameter list, and then later iterate that list of types.

However, I'm running into a problem when iterating the types, because the initial Tuple has null members, so calling .GetType() gives me a NullReferenceException.

I realize I could do what I need with an actual list of Type objects, but I'd prefer the very concise syntax that's allowed when creating tuples... and of course because things like this intrigue me :)

public static void IterateTupleMemberTypes<T>() where T : ITuple, new()
{
   var tuple = new T();
   for (var i = 0; i < tuple.Length; ++i)
   {
      //First call to GetType() succeeds, first element is an int.
      //Second call to GetType() fails (null ref ex), second element is a string.
      Console.WriteLine($"Item{i} Type: {tuple[i].GetType()}");
   }
}

Usage

public class CustomClass
{
   public int ID { get; set; }
}

IterateTupleMemberTypes<(int, string, CustomClass)>();
Brett Rossier
  • 3,420
  • 3
  • 27
  • 36
  • 1
    Getting the type parameters of a `ValueType<>` type is exactly the same as getting the type parameters of any other generic type. Like `Dictionary`, as in marked duplicate. – Peter Duniho Jan 04 '18 at 02:17
  • Perfect, thanks. Guess I was so focused on using ITuple's indexer, I didn't even think about that. – Brett Rossier Jan 04 '18 at 05:02
  • Don't use this as a dupe target, using reflection isn't necessary for this... – jrh Aug 19 '20 at 15:02

1 Answers1

0

I think you are mixing data and metadata. The first call succeed since int is a value type, and default(int) assigns the value to 0, so it works. This won't do for reference types, since these are assigned initially to null.

I believe the proper approach here is, well, reflection - and iterating over the properties of the type, without the need to create an instance (so the new() restriction is redundant).

public static void IterateTupleMemberTypes<T>() where T : ITuple
{
    var tupleGenericArguments = typeof(T).GetGenericArguments();
    for (var i = 0; i < tupleGenericArguments.Length; ++i)
    {
        Console.WriteLine($"Item{i} Type: {tupleGenericArguments[i].Name}");
    }
}
  • Must disagree - reflection won't help you in case you insist of using indexers - that is accessing the data. You need to work with the metadata - in this case getting the generic arguments of typeof(T), I've added a code snippet. – Sasha Alperovich Jan 04 '18 at 02:04
  • Woops, I stand corrected, haven't used `ITuple` at all. – InBetween Jan 04 '18 at 02:08