16

I want to Map a ValueTuple to a class using reflection. Documentation says that there is a Attribute attached to ValueTuple with parameters names (others than Item1, Item2, etc...) but I can't see any Attribute.

Disassembly shows nothing.

What's happens?

Example:

public static T ToStruct<T, T1,T2>(this ValueTuple<T1,T2> tuple) where T : struct

Via reflection can't get Item1, Item2 names to match with T fields via reflection.

RamonEeza
  • 623
  • 6
  • 18

2 Answers2

22

You should have the TupleElementNames attribute on the method created by the compiler.

See this code:

public class C {
    public (int a, int b) M() {

        return (1, 2);
    }
}

Which compiles to:

[return: TupleElementNames(new string[] {
    "a",
    "b"
})]
public ValueTuple<int, int> M()
{
    return new ValueTuple<int, int>(1, 2);
}

You can get that attribute using this code:

Type t = typeof(C);
MethodInfo method = t.GetMethod(nameof(C.M));
var attr = method.ReturnParameter.GetCustomAttribute<TupleElementNamesAttribute>();

string[] names = attr.TransformNames;
Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
  • public static T ToStruct(this ValueTuple tuple) where T : struct Compiler NO adds anything to Match ValueTuple with TupleElementNames... – RamonEeza Apr 19 '17 at 07:24
  • It is valid only to RETURN a ValueTuple. I want use a ValueTuple as Input, not output – RamonEeza Apr 19 '17 at 07:29
  • No, it is valid for method arguments too. In your code you won't have any arguments since you use the `ValueType` itself. If you would use the actual type it could have. – Patrick Hofman Apr 19 '17 at 07:30
  • There is no other possibility. I have to admit ANY valuetuple to map to – RamonEeza Apr 19 '17 at 07:35
  • 3
    We can talk for very long about this, but it won't work, as already said. The `ValueType` itself doesn't hold that kind of information, so when you use that type, you are lost. – Patrick Hofman Apr 19 '17 at 07:36
12

As Patrick pointed out above, you can use reflection to inspect the tuple names used in the declaration of your method. But that gives you no information given that your ToStruct method signature shows no names. And, in any case, that gives you no information about tuples that will actually be passed into that method.

The runtime type is only ValueTuple (no names). The names only help at compile time, as syntactic sugar for ItemN.


From the design notes:

Name erasure at runtime

Importantly, the tuple field names aren't part of the runtime representation of tuples, but are tracked only by the compiler.

As a result, the field names will not be available to a 3rd party observer of a tuple instance - such as reflection or dynamic code.


You can read more about that at http://mustoverride.com/tuples_names/

Julien Couvreur
  • 4,473
  • 1
  • 30
  • 40