C# ValueTuple 属性命名

10
我正在尝试C#中的ValueTuple类,并且我对属性命名有疑问,让我们看看:
如果像这样声明对象实例化ValueTuple:var tuple1 = (Name: "Name1", Age: 25);,我们可以给属性命名, 但是,如果像这样:ValueTuple<string,int> tuple2 = (Name: "Name1", Age: 25);,我们会收到一个警告,提示名称被忽略, 因此,我们应该输入:ValueTuple<string,int> tuple2 = ("Name1",25); 然后属性将是tuple2.Item1tuple2.Item2
有人能向这个新手解释一下原因吗?
提前感谢您。

ValueTuple只是普通C#类型,没有编译器的特殊支持。它的成员总是称为"Item1"、"Item2"等等。然而,"(x, y)"元组语法具有编译器的特殊支持,引入了元组成员的其他名称,并将它们映射到生成的IL代码中适当的“ValueType”名称。 - Matthew Watson
但是,像这样:ValueTuple<string,int> tuple2 = (Name: "Name1", Age: 25);,我们不会出现错误 - 至少在你展示的代码中不会。你会收到警告,表示元组字面量中的名称被有效地忽略了,但你不会遇到错误。 - Jon Skeet
可能是Name ValueTuple properties when creating with new的重复问题。 - Rekshino
3个回答

22

这里涉及到两种不同的元组:" .NET ValueTuple<...>" 类型和 C# 元组类型。C# 元组类型可以有元素名称;而 "ValueTuple<...>" 类型则不能(在常规方式下,简单来说类型系统中没有地方容纳它们)。

在执行时,值只知道它的 .NET 类型。例如,如果使用:

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

那么DoSomethingWithValue将无法区分两个元组值之间的差别。这些信息只能在编译时获得。

关于参数和返回类型的元素名称信息是通过C#编译器使用的属性传播的。例如,像这样声明的方法:

public (string name, int score) GetFoo()

编译后的IL代码就好像它被声明为这样:

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

C#语言定义了合适的转换方式,将.NET类型和C#元组类型之间进行无缝转换。

在使用元组方面,尽可能使用C#元组类型,为元组中的元素命名可以极大地提高其可用性。


7
谢谢Jon,他帮了我很多,让我理解了发生了什么事情,并且这个C# 7段落也有所帮助。链接为http://josephwoodward.co.uk/2017/04/csharp-7-valuetuple-types-and-their-limitations - Ferus7

3
你想定义的是什么。
(string Name,int Age) tuple1 = (Name: "Name1", Age: 25);

你正在定义的是什么。
ValueTuple<string,int> tuple2 = (Name: "Name1", Age: 25);

看一下您正在定义的Type之间的差异。如果您考虑名称,它们是两个不同的东西。


2
这完全没有回答问题 - 在两种情况下,底层类型都是ValueTuple(另外,OP使用的var示例等同于您的第一个示例) - UnholySheep
OP想知道它们为什么不同。这是因为它们是不同类型的原因。 - Anup Sharma
2
它们不是不同的类型。尝试您的代码并添加 Console.WriteLine(tuple1.GetType().FullName);Console.WriteLine(tuple2.GetType().FullName); - Matthew Watson
1
它们在编译时是不同类型,但在执行时却相同。就像“dynamic”和“object”一样。 - Jon Skeet

-1
简而言之:不,您不能像这样创建具有命名字段的ValueTuples。
详细来说:请看使用new创建Name ValueTuple属性 - 您的问题在那里得到了很好的回答。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接