33

I know I can name parameters when I create a tuple implicitly like:

var me = (age: 21, favoriteFood: "Custard");

Is it possible to name parameters when a tuple is created explicitly? i.e.

var me = new ValueTuple<int, string>(21, "Custard");
BanksySan
  • 27,362
  • 33
  • 117
  • 216
  • Related posts - [Better naming in Tuple classes than “Item1”, “Item2”](https://stackoverflow.com/q/7745938/465053) & [How to name tuple properties?](https://stackoverflow.com/q/27908630/465053) – RBT May 30 '18 at 07:41

5 Answers5

40

No, you can't. The ValueTuple types are actually independent of the named field support in C#. The latter works more like named properties for anonymous types. That is, the compiler analyzes the code and generates aliases to the appropriate members according to your declarations and usages. It is through the assignment that the compiler learns the names of the fields. Since the basic constructor syntax doesn't provide a mechanism to name the fields, you can't use that to directly generate a tuple with named fields.

Of course, there are ways you can re-interpret the value returned from the constructor syntax, to assign names to that returned value. I'm assuming you're aware of that approach and are looking for something more direct.

As an example of what I mean by "re-interpret", you could do something like this:

static (int value, string text) ConvertToNamed((int, string) t) => t;

then this would name the fields, in a new variable:

var t1 = new ValueTuple<int, string>(21, "hello");
var t2 = ConvertToNamed(t1);

The variable t1 is stuck with Item1 and Item2. But the compiler will implicitly generate the desired names for the variable t2.

Maybe a better example is one where you don't require the additional method:

(int value, string text) t = new ValueTuple<int, string>(21, "hello");

Again, you're not really naming the fields in the constructor syntax, but they are reinterpreted by the local variable declaration.

This is probably not a serious limitation. In a scenario where there's a desire to have a persistent, easily-assigned name, it's probably better to declare a user-defined type than to use the tuple syntax anyway. You can write deconstructors for user-defined types as well, and declaring types like that means the names are first-class citizens when it comes to reflection, dynamic, etc.

Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
  • Are you saying you can set the names after the declaration? – BanksySan Apr 23 '17 at 00:25
  • Not for that variable, no. But you can pass the value through other syntax that will set the names. I'll add one example above. – Peter Duniho Apr 23 '17 at 00:30
  • I think I know what you're saying. Thanks. – BanksySan Apr 23 '17 at 00:30
  • 3
    is there any reason why the method is `(int value, string text) ConvertToNamed((int value, string text) t)` rather than just `(int value, string text) ConvertToNamed((int, string) t)`? – svick Apr 23 '17 at 10:42
  • @svick: force of habit? No, I guess not. :) the method doesn't use any of the tuple fields, so of course there's not really any reason to name them. It would work just as well without. – Peter Duniho Apr 23 '17 at 17:36
0

You can cast to named tuple during assignment:

var me = ((int value, string text)) new ValueTuple<int, string>(21, "Custard");
  • Please explain how that syntax would be preferred over `(age: 21, favoriteFood: "Custard")` (i.e. the usual, natural way to achieve the same thing). – Peter Duniho Mar 20 '20 at 02:57
  • Basically, this variant is helpful when syntax sugar for named tuples still not acceptable like EF lambda operations ie Join, Select etc. – user3875682 Mar 21 '20 at 08:30
  • Please provide an example. I'm not aware of any context where _"syntax sugar for named tuples still not acceptable"_, certainly not when dealing with LINQ operators. – Peter Duniho Mar 21 '20 at 16:20
  • This is an example from my code: `_dbContext.Products .Where(p=>p.Id == productId) .Join(ProductDetails, p=>p.Id, pd=>pd.Id, (p, pd) =>((Product Product, ProductDetail Detail)) new ValueTuple(p, pd)) .ProjectTo(_mapper.ConfigurationProvider).ToListAsync(cancellationToken);` Actually I didn't find working way to map 2 joined tables into 1 DTO except that one. – user3875682 Apr 27 '20 at 02:56
0

... C# 7.0 doesn’t enable the use of custom item names when using the explicit System.ValueTuple<…> data type. Therefore, if you replace var in Example 8 of Figure 1, you’ll end up with warnings that each item name will be ignored.

Source

I'm posting this answer because the closest the docs come to explaining this is:

Data members of ValueTuple types are fields. Data members of Tuple types are properties.

Ryan Pavlik
  • 1,723
  • 1
  • 11
  • 20
Jpsh
  • 1,697
  • 12
  • 17
0

Was looking for this when using ValueTuple in Linq. I did a F2-rename variable and it created the following syntax:

var query = from x in myList
select (First: x.something, Second: x.other) into g
select new Whatever(g.First, g.Second);
-4

I don't believe so. Here are docs that I found on ValueTuple:

https://learn.microsoft.com/en-us/dotnet/api/system.valuetuple-7?view=netframework-4.7

I personally have not used the ValueTuble type. I have used the Tuple class before like this:

var tuple = new Tuple<int, string>(21, "Custard");
var number = tuple.Item1;
var st = tuple.Item2;

However I find using Tuples, especially when passed thru methods to be clunky. Always having to know what is in Item1 and Item2 etc. According to the ValueTuple docs, it is used in the same way.

Shouldn't you just make an entity class?

I have used the Anonymous Type which I think will suit your needs.

var anyom = new
{
    age = 21,
    favoriteFood = "Custard"
};

number = anyom.age;
st = anyom.favoriteFood;
theDude
  • 3
  • 3
  • No it isn't, @BanksySan. The compiler has special behaviors when dealing with `ValueTuple structs`, but the types themselves have `Item1`, `Item2`, etc. like `Tuple` classes have properties. – Paulo Morgado Apr 23 '17 at 16:02
  • @PauloMorgado Aye, my mistake. The 'magic' is in the language, not the IL. – BanksySan Apr 23 '17 at 16:03
  • I agree with Paulo Morgado: the compiler isn't the interpreter, @BanksySan, but the component that translates the code into a non-human readable format, which IL interpreter runs. Downvoted theDude's answer. – Davide Cannizzo Jan 25 '18 at 14:39
  • I guess deleting the bad answer won’t hurt anybody. – Yarl Feb 28 '19 at 17:01