10

I'm trying ValueTuple Class in C#, and i have a doubt about properties naming, let's see:

If instantiate a ValueTuple declaring the object like this: var tuple1 = (Name: "Name1", Age: 25); We can name the properties,

but, like this: ValueTuple<string,int> tuple2 = (Name: "Name1", Age: 25);

we get a warning that says the names are ignored,so

We should type: ValueTuple<string,int> tuple2 = ("Name1",25);

Then the properties will be tuple2.Item1 and tuple2.Item2

Can someone explain this newbie the reason about this?

Than you in advantage

Ferus7
  • 707
  • 1
  • 10
  • 23
  • `ValueTuple` is just a normal C# type with no special support from the compiler. It's members are always called `Item1`, `Item2` and so on. However, the `(x, y)` tuple syntax has special support from the compiler which introduces other names for the tuple members and maps them to the appropriate `ValueType` names in the generated IL code. – Matthew Watson Oct 06 '17 at 08:50
  • "but, like this: `ValueTuple tuple2 = (Name: "Name1", Age: 25);` we get an error" - no you don't; not on the code you've shown. You get warnings that the names in the tuple literal are effectively ignored, but you don't get an error. – Jon Skeet Oct 06 '17 at 08:51
  • Possible duplicate of [Name ValueTuple properties when creating with new](https://stackoverflow.com/questions/43565738/name-valuetuple-properties-when-creating-with-new) – Rekshino May 17 '18 at 07:26

3 Answers3

22

There are two different "kinds" of tuples involved here: the .NET ValueTuple<...> types, and C# tuple types. C# tuple types can have element names; ValueTuple<...> types can't. (There's simply nowhere in the type system for that to live in a normal way.)

At execution time, a value is only aware of its .NET type. For example, if you use:

(string x, int y) tuple1 = ("hello", 10);
(string a, int b) tuple2 = ("hello", 10);
DoSomethingWithValue(tuple1);
DoSomethingWithValue(tuple2);
...
void DoSomethingWithValue(object value) { ... }

then DoSomethingWithValue wouldn't be able to distinguish between the two tuple values at all. The information is only available at compile-time.

Information about element names for things like parameters and return types is propagated via attributes that the C# compiler consumes. So for example, a method declared like this:

public (string name, int score) GetFoo()

is compiled in IL as if it had been declared like this:

[TupleElementNames(new string[] { "name", "score" }]
public ValueTuple<string, int> GetFoo()

The C# language defines appropriate conversions between the .NET types and the C# tuple types to make it as seamless as possible.

In terms of how to use tuples, I'd use the C# tuple types as far as you can. Naming the tuple elements makes a huge difference in usability.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 7
    Thank you Jon, this helped me a lot to understand what is going on, and [this](http://josephwoodward.co.uk/2017/04/csharp-7-valuetuple-types-and-their-limitations) C# 7 paragraph helped too – Ferus7 Oct 06 '17 at 09:34
2

What you want to define is

(string Name,int Age) tuple1 = (Name: "Name1", Age: 25);

what you are defining is

ValueTuple<string,int> tuple2 = (Name: "Name1", Age: 25);

Look at the difference between in Type you are defining. Both are two different things if you take the name.

Anup Sharma
  • 2,053
  • 20
  • 30
  • 2
    That does not answer the question at all - the underlying type is a `ValueTuple` in both cases (also the `var` example OP used is equivalent to your first example) – UnholySheep Oct 06 '17 at 08:47
  • OP wants to know why they are different. That's what I have given here as both are different types. – Anup Sharma Oct 06 '17 at 08:49
  • 2
    They ARE NOT different types. Try your code and add `Console.WriteLine(tuple1.GetType().FullName);` and `Console.WriteLine(tuple2.GetType().FullName);` – Matthew Watson Oct 06 '17 at 08:51
  • 1
    They are different types at compile-time, but not at execution time. Just like `dynamic` and `object`. – Jon Skeet Oct 06 '17 at 08:52
-1

In short: No, you can't create ValueTuples with named fields like this.

In detail: Have a look at Name ValueTuple properties when creating with new - your question is answered very well there.

michivo
  • 89
  • 6