AlePorro
AlePorro

Reputation: 131

How do I correctly assign names to a named tuple in a list

I have the following code and it seems to work fine, but when I inspect the tuples inside the list they are named Item1,Item2,Item3 instead of the names I have assigned to them. What am I doing wrong? (The code references System.ValueTuple.)

Thank you for your help.

var listContent = new List<(string date, double value, DateTime datetime)>();

// Read the file just created and put values in list of tuples
using (var reader = new StreamReader(rawFileName))
{
   while (!reader.EndOfStream)
   {
      var line = reader.ReadLine();
      var values = line.Split(',');
      listContent.Add((date: values[0],
         value: Convert.ToDouble(values[2]),
         datetime: DateTime.ParseExact(values[0], "yyyy-MM-dd", null)));
    }
}

If I put a breakpoint just after the above code, in the Immediate Window I can do the following, which is even more puzzling:

listContent[0]
("2017-01-01", 17.193, {01/01/2017 00:00:00})
    date: "2017-01-01"
    value: 17.193
    datetime: {01/01/2017 00:00:00}
    Raw View: ("2017-01-01", 17.193, {01/01/2017 00:00:00})
listContent[0].Item1
null
listContent[0].date
null
listContent[0].dummy
error CS1061: '(string date, double value, DateTime datetime)' does not contain a definition for 'dummy' and no accessible extension method 'dummy' accepting a first argument of type '(string date, double value, DateTime datetime)' could be found (are you missing a using directive or an assembly reference?)

[UPDATE]

I have super-simplified the code:

var listContent = new List<(string str1, string str2)>();
for (var n = 1; n < 100; n++)
{
   var tpl = (str1: "hello" + n.ToString(), str2: "world" + n.ToString());
   listContent.Add(tpl);
}
var z = listContent[0].str1;

and check out what the immediate window gives me:

z
"hello1"
listContent[0].str1
null

So I'm not going crazy: the tuples are assigned correctly but for some bizarre reason the immediate window still gives me null for listContent[0].str1 ???

Upvotes: 0

Views: 1262

Answers (1)

madreflection
madreflection

Reputation: 4967

Tuple element names are not part of the type. The compiler translates the name to the associated ItemN property.

With the exception of local variables (which cannot have attributes applied to them), the names are conveyed in the [TupleElementNames] attribute. If you were to declare listContents as a field, for example, it would have the following attribute applied to it:

[TupleElementNames(new string[] { "date", "value", "datetime" })]

When you hovered over listContents with the mouse cursor, the debugger only saw the list instance and the tuple instances within it. Given an instance, tuple elements names are not available. You would need an accompanying PropertyInfo, FieldInfo, or ParameterInfo so you can get the TupleElementNamesAttribute that conveys the names. If you made it a field, though, the debugger still only looks at the instance.

I can't explain the behavior in the Immediate window, and the Watch window seems to have the same problem. Looks like you found a bug in Visual Studio.

Upvotes: 2

Related Questions