问题 在select语句中使用命名元组


有没有更好的方法使用var目标变量在C#7中选择一个命名元组?我必须在示例1中做错事,或者完全误解某些事情。我似乎必须明确设置目标类型才能执行此操作。

//1. Fails to compile with "incorrect number of type parameters" issue.
var tuples = source.Select<(int A, int B)>(x => (x.A, x.B));

//2. Compiles
IEnumerable<(int A, int B)> tuples = toCheck.Select(x => (x.A, x.B));

//3. Compiles
var tuples = new HashSet<(int A, int B)>(source.Select(x => (x.A, x.B)));

8041
2017-08-11 09:36


起源



答案:


你可以使用 var,但您需要确保实际命名元组元素。

在C#7.0中,您需要明确地执行此操作:

var tuples = source.Select(x => (A: x.A, B: x.B));
foreach (var tuple in tuples)
{
    Console.WriteLine($"{tuple.A} / {tuple.B}");
}

在C#7.1中,当从属性或字段中获取元组文字中的值时,该标识符将隐式地是元素名称,因此您将能够编写:

var tuples = source.Select(x => (x.A, x.B));
foreach (var tuple in tuples)
{
    Console.WriteLine($"{tuple.A} / {tuple.B}");
}

专题文件 有关兼容性等的详细信息


14
2017-08-11 10:07



好极了,我没有意识到你可以在声明中嵌入元组中的元素名称。 - gmn
出于好奇,为什么不是这样 A= x.A 在匿名类型? var x = new { A = x.A, B = x.B }; - Rand Random
@RandRandom:这不是元组元素名称的语法。一贯的 : 在声明和元组文字中。匿名类型更像是对象初始化器,“设置”属性(尽管类型实际上是不可变的) - Jon Skeet
That's just not the syntax for tuple element names. 这有点像我的问题,为什么他们没有使用相同的语法?看起来很奇怪,因为它 feels 类似的,对于像我这样不知道背后的魔法的开发者。 - Rand Random
@RandRandom:忽略声明。但它 是 用于提供参数名称的相同语法。就个人而言,我没关系 - 如果有的话,我想如果匿名类型使用了冒号,我会更喜欢它。 - Jon Skeet


答案:


你可以使用 var,但您需要确保实际命名元组元素。

在C#7.0中,您需要明确地执行此操作:

var tuples = source.Select(x => (A: x.A, B: x.B));
foreach (var tuple in tuples)
{
    Console.WriteLine($"{tuple.A} / {tuple.B}");
}

在C#7.1中,当从属性或字段中获取元组文字中的值时,该标识符将隐式地是元素名称,因此您将能够编写:

var tuples = source.Select(x => (x.A, x.B));
foreach (var tuple in tuples)
{
    Console.WriteLine($"{tuple.A} / {tuple.B}");
}

专题文件 有关兼容性等的详细信息


14
2017-08-11 10:07



好极了,我没有意识到你可以在声明中嵌入元组中的元素名称。 - gmn
出于好奇,为什么不是这样 A= x.A 在匿名类型? var x = new { A = x.A, B = x.B }; - Rand Random
@RandRandom:这不是元组元素名称的语法。一贯的 : 在声明和元组文字中。匿名类型更像是对象初始化器,“设置”属性(尽管类型实际上是不可变的) - Jon Skeet
That's just not the syntax for tuple element names. 这有点像我的问题,为什么他们没有使用相同的语法?看起来很奇怪,因为它 feels 类似的,对于像我这样不知道背后的魔法的开发者。 - Rand Random
@RandRandom:忽略声明。但它 是 用于提供参数名称的相同语法。就个人而言,我没关系 - 如果有的话,我想如果匿名类型使用了冒号,我会更喜欢它。 - Jon Skeet


Select 需要2个类型参数: Select<TSource, TResult>。一个元组 (int A, int B) 只有一种类型,你也可以写它 ValueTuple<int, int>。因此,如果需要命名元组,则必须编写两个参数

var tuples = source.Select<TypeOfSource, (int A, int B)>(x => (x.A, x.B));

-1
2017-08-11 09:49