5

I used a reflection to get a return value of type object, but its actual type is (int[], string[]) I have double check with obj.GetType().ToString() and it prints System.ValueTuple`2[System.Int32[],System.String[]].

But just casting with ((int[], string[]))obj or (ValueTuple<int[],string[]>)obj return that the cast is invalid. How to correctly do this?

5argon
  • 3,683
  • 3
  • 31
  • 57
  • 3
    You need an extra set of parentheses for the first cast: `((int[], string[]))obj`. – Zev Spitz Jun 24 '18 at 11:36
  • Ah, yes sorry that is what I was doing and it returns the cast is invalid. – 5argon Jun 24 '18 at 11:36
  • 1
    Could it be that your project is targeting an older C# language version, which doesn't support tuples? – Zev Spitz Jun 24 '18 at 11:40
  • Why you need to do this kind of thing? Maybe explaining what you're trying to achieve can lead you to a correct solution. – CodeNotFound Jun 24 '18 at 11:43
  • would be useful to see the code, but I seem to recall sometimes getting this when I should be casting object.Value. (stepping through in debug should show you this). –  Jun 24 '18 at 12:25
  • So it is supposed to work? I will add a short reproduce code with the latest C# version later. – 5argon Jun 24 '18 at 12:30
  • 1
    I mean try: ((int[], string[]))obj.Value . If this doesn't work, try GetType, GetProperty, GetValue as in Heinzi's answer here: https://stackoverflow.com/questions/8631546/get-property-value-from-c-sharp-dynamic-object-by-string-reflection –  Jun 24 '18 at 12:37
  • Use new ValueTuple() { obj.xxxx, obj.yyy}; – jdweng Jun 24 '18 at 13:26
  • @JeffDavies `GetField` works. Thanks. – 5argon Jun 24 '18 at 14:53

1 Answers1

2

Ok I finally got it working.

It is possible to further reflect the ValueTuple's Field ItemX. Not sure if there are other less forced ways where we can get the tuple as a whole.

using System;

namespace CTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Test t = new Test();
            var tuple = typeof(Test).GetMethod(nameof(t.ReturnTuple)).Invoke(t, null);
            int[] i = (int[])typeof((int[], string[])).GetField("Item1").GetValue(tuple);
            string[] s = (string[])typeof((int[], string[])).GetField("Item2").GetValue(tuple);

            foreach (int data in i)
            {
                Console.WriteLine(data.ToString());
            }
            foreach (string data in s)
            {
                Console.WriteLine(data);
            }

            // Output :
            // 1
            // 2
            // 3
            // a
            // b
            // c
        }
    }

    class Test
    {
        public (int[], string[]) ReturnTuple() => (new int[] { 1, 2, 3 }, new string[] { "a", "b", "c" });
    }
}
5argon
  • 3,683
  • 3
  • 31
  • 57