0

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 ???

AlePorro
  • 111
  • 1
  • 11
  • So is this a compile time error? `listContent[0].date`? – gunr2171 Jun 20 '19 at 16:53
  • In [my example](https://i.stack.imgur.com/azbsH.png) I'm seeing the correct properties for each element, not "Item1". – gunr2171 Jun 20 '19 at 16:57
  • A new Tuple() (A class in Net library) properties are Item1, Item2, Item, .... You cannot change the property name to a value. – jdweng Jun 20 '19 at 16:59
  • What is the version of Visual Studio you are using? – Jeppe Stig Nielsen Jun 20 '19 at 17:00
  • I haven't personally used named tuples yet, but my understanding is that you name attributes where the tuple type is declared - i.e. in the `var listContent = new List<...` statement in your case. – 500 - Internal Server Error Jun 20 '19 at 17:07
  • @gunr2171 no actually it doesn't give error, as you see in the Immediate Window queries I made I can actually call listcontent[0].date, but it returns null. Yet, the list IS populated with tuples with non-null values. I am using Visual Studio Community 2017 – AlePorro Jun 20 '19 at 17:13
  • How did you "inspect the tuples" such that you didn't see the element names? What exactly is puzzling about that output? – madreflection Jun 20 '19 at 17:15
  • I inspected them hovering with the mouse over list. And what is puzzling is that the list is populated, I can see the content of listContent[0], as you can see in the immediate windown, and yet I cannot call listContent[0].date, or better, it returns null. – AlePorro Jun 20 '19 at 17:26
  • I guess I didn't examine the output closely enough. The hovering thing can be explained, though... – madreflection Jun 20 '19 at 17:50
  • The same issue in the Immediate Window is seen with Visual Studio Professional 2019. – Jeppe Stig Nielsen Jun 20 '19 at 20:50
  • If anybody is interested, it was confirmed as a bug, apparently coreclr. https://github.com/dotnet/coreclr/issues/25519 – AlePorro Jul 09 '19 at 06:56

1 Answers1

2

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.

madreflection
  • 4,744
  • 3
  • 19
  • 29
  • Thank you, this was a very informative answer, although, as you pointed out, the Immediate Window and Watch Window's behavior is probably buggy. Looking at the comments above it doesn't seem to be any better in VS 2019 either! – AlePorro Jun 22 '19 at 20:08