C#元组

元组表示一个或多个多个数据组成的类型。

从功能上看,元组相当于多个没有名称,仅仅包含属性的类或结构。

一般的,元组多作为返回值,因为参数本就支持多个。

元组的使用

C#中使用System.Tuple<T>表示元组。类型同时包括多个泛型参数的类型。

元组类型是只读的,可以通过ItemN属性访问对应元素。

元组实现了Equals,GetHashCode方法,通过使用每个属性。

可以通过元组实现多返回值

public static Tuple<string,string> GetFullName(){
    return new Tuple<string,string>("hello","kitty");
}

System.Tuple类有多个静态方法Create,用来辅助创建元组。


public static Tuple<string,string> GetFullName(){
    return Tuple.Create("hello","kitty");
}

使用元组

var tuple = GetFullName();
Console.WriteLine(tuple.Item1);
Console.WriteLine(tuple.Item2);

元组的缺点是他的成员名称都是固定的,没有具体的意义,因此一般都很少使用元组。

更强大的元组

从C#7.0开始,支持更加简单的元组语法。

public static (string,string) GetFullName(){
    return ("hello","kitty");
}

新元组的类型是System.ValueTuple<T>,同样,支持多个泛型参数。

使用新元组可能需要引入System.ValueTuple包。

System.Tuple<T>相比,新元组是结构类型,并且成员都是字段,因此是可变的。

新元组是可以通过字段ItemN读写元素。

新元组通过字段实现,因此更高效,并且可以作为out,ref参数。

新元组也实现了Equals,GetHashCode方法,通过每个字段。

新元组不是只读的,因此作为字典的键时,要注意添加之后不能修改。

元组元素命名

作为参数和返回值的元组命名

可以为元组的元素命名

public static (string firstName,string lastName) GetFullName(){
    return ("hello","kitty");
}

在编译后,名称会通过TupleElementNamesAttribute特征保留。

作为局部变量的元组

在局部变量中,元组命名仅存在于源代码

    public static void F2()
    {
        (int low, int high) range = (1, 100);

        Console.WriteLine(range.low);
        Console.WriteLine(range.high);
    }

编译后的代码访问的是rangeItem1Item2字段。

元组赋值和元素名称

类型相同,名称不同的元组可以进行赋值。

public static void F2()
{
    (int low, int high) range = (1, 100);

    (int start, int end) range2 = range;
}

即使进行赋值的元组之间有成员名称相同,赋值是也是按照顺序进行,而非按照名称。

    public static void F4()
    {
        (int low, int high) range = (1, 100);

        (int high, int higher) range2 = range;

        Console.WriteLine(range2.high);
        Console.WriteLine(range2.higher);
    }

元组之间赋值只认顺序,不认名称。

元组的隐式转换

只要元组的对应元素之间支持隐式转换,元组就可以进行隐式转换。

public static void F5()
{
    (short low, short high) range = (1, 100);

    (int high, int higher) range2 = range;

    Console.WriteLine(range2.high);
    Console.WriteLine(range2.higher);
}

解构

同时定义多个变量来接收元组的多个元素。

 (var fisrtName, var lastName) = GetFullName();

弃元

结构元组时,如果只需要访问部分元素,可以使用_作为占位符丢弃元素。

 (var fisrtName, _) = GetFullName();

总结

虽然元组拥有不少的功能,但总体还是比较鸡肋。

因此:要支持多返回值,建议自行定义类或者结构。