元组(TupleValueTuple)

Posted heyangming

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了元组(TupleValueTuple)相关的知识,希望对你有一定的参考价值。

一、元组可以用来干什么呢,我们知道数组可以用来存储相同类型的对象(object[]除外)元组可以用来组合不同类型的对象
1、元组的声明和初始化(用圆括号来声明元组)
声明及初始化的三种方式:
1>(string a,int i,Person p) t=("magic",42, new Person("Stephanie","Nagel")) 调用方式:$"{t.a}{t.i}{t.p}"
2>利用var关键字;var t=("magic",42, new Person("Stephanie","Nagel")) 调用方式:$"{t.Item1}{t.Item2}{t.Item3}"
3>通过命名参数:var t=(s:"magic",i:42,p:new Person("Stephanie","Nagel")) 调用方式:$"{t.s}{t.i}{t.p}"
二、元组解构(解构顾名思义就是分解变量,将一个总的变量分解成各自的变量)
1、将元组分解为变量,我们上面的例子都利用的元组变量,当我们删除元组变量的时候,即可将元组变量分解
1>(string s,int i,Person p) =("magic",42, new Person("Stephanie","Nagel")) 调用方式:$"{s}{i}{p}"
2>var关键字声明解构:(var s,var i,var p) =("magic",42, new Person("Stephanie","Nagel")) 调用方式:$"{s}{i}{p}"
3>如果不需要所有的元组部分,可以直接使用""忽略改部分:(string s,,_) =("magic",42, new Person("Stephanie","Nagel")) 调用方式:$"{s}"
三、返回元组的方法
这里涉及到怎么去返回值里面定义元组的方法,举例说明:
public static (int result, int remainder) Divide(int dividend, int divisor)
{
int result = dividend / divisor;
int remainder = dividend % divisor;
return (result, remainder);
}
四、幕后的工作原理
这里我们需要区分Tuple类和ValueTuple结构,从定义上我们知道结构和类最大的区别在于一个在堆上一个在栈上,在堆上使用Tuple进行存储时,会有垃圾收集器需要工作会消耗性能,ValueTuple结构在栈上就不存在这种问题,
这也就是我们在什么时候选择使用结构的一个标准,当我们需要小的数据结构的时候,就使用结构
我们发现Tuple这个类是一个只读属性的不变的类,而ValueTuple这个结构成员是公共的随时可以进行访问,可以进行值的变更,
Tuple类是没有构造函数的,创建他的唯一方式就是使用Tuple.Create来创建
举例说明:
// old tuple is a immutable reference type
Tuple<string, int> t1 = Tuple.Create("old tuple", 42);
//t1.Item1 = "new string"; // not possible with Tuple
// new tuple is a mutable value type
(string s, int i) t2 = ("new tuple", 42);
t2.s = "new string";
t2.i = 43;
t2.i++;
Console.WriteLine($"new string: {t2.s} int: {t2.i}");
//利用特性指定返回元组方法返回值的返回类型,指定了名称也就指定了返回类型
[return: TupleElementNames(new string[] {"result", "remainder" })]
五、兼容性(Tuple和ValueTuple)
1、不可避免的,虽然ValueTuple的结构类型比Tuple类在性能上会优化很多,但是我们还是需要根据自己的需求对两者来进行转化
采用ToValueTuple可以将Tuple转化成ValueTuple,同样我们可以利用ToTuple将ValueTuple转化成Tuple,举例说明:
// 创建元组类的元组
Tuple<string, int, bool, Person> t1 = Tuple.Create("a string", 42, true, new Person("Katharina", "Nagel"));
Console.WriteLine($"old tuple - string: {t1.Item1}, number: {t1.Item2}, bool: {t1.Item3}, Person: {t1.Item4}");
//t1.Item1 = "a";此时我们发现对于Tuple创建的元组的值是无法赋值的
//转化成ValueTuple
(string s, int i, bool b, Person p) t2 = t1.ToValueTuple();
//t2.i = 44;此时我们发现元组可以重新赋值了,
Console.WriteLine($"new tuple - string: {t2.s}, number: {t2.i}, bool: {t2.b}, Person: {t2.p}");
(string s, int i, bool b, Person p) = t1; // Deconstruct
Console.WriteLine($"new tuple - string: {s}, number: {i}, bool: {b}, Person {p}");
// convert ValueTuple to Tuple
Tuple<string, int, bool, Person> t3 = t2.ToTuple();
Console.WriteLine($"old tuple - string: {t1.Item1}, number: {t1.Item2}" +
$", bool: {t1.Item3}, Person: {t1.Item4}");
六、推断元组的名称(将已经定义的数据类型的元组赋值给另一个元组,同样可以进行调用赋值的数据的定义类型)
七、元组与链表
举例说明:
//创建int类型的链表
var list = new LinkedList(Enumerable.Range(0, 10));
int value;
//获取第一个节点
LinkedListNode node = list.First;
do
{
//利用解构将数据传入元组
(value, node) = (node.Value, node.Next);
Console.WriteLine(value);
} while (node != null);
Console.WriteLine();
八、元组和LINQ
主要是匿名类和元组的区别
1、匿名类用花括号表示,举例说明:
var racerNamesAndStarts = Formula1.GetChampions()
.Where(r => r.Country == "Italy")
.OrderByDescending(r => r.Wins)
.Select(r => new
{
r.LastName,
r.Starts
});
2、元组用括号表示,举例说明:
var racerNamesAndStarts = Formula1.GetChampions()
.Where(r => r.Country == "Italy")
.OrderByDescending(r => r.Wins)
.Select(r =>
(
r.LastName,
r.Starts
));
九、类型解构
这里我们要说的是如何给给任意类型进行解构,利用到了out关键字,为甚么要用关键字out来输出多类型的返回呢,因为方法重载
重载的定义是什么,重载就是方法签名相同,返回值相同,如果使用元组就无法达到这一目的
只有类型有解构方法,才能利用解构赋值到元组,当然也可以通过扩展方法进行扩展
举例说明:
//解构方法
public void Deconstruct(out string firstName, out string lastName)
{
firstName = FirstName;
lastName = LastName;
}
//调用
var p1 = new Person("Katharina", "Nagel");
//如果没有解构方法,此函数就会报错
(var first, var last) = p1;
//扩展解构
public static class RacerExtensions
{
public static void Deconstruct(this Racer r, out string firstName, out string lastName, out int starts, out int wins)
{
firstName = r.FirstName;
lastName = r.LastName;
starts = r.Starts;
wins = r.Wins;
}
}

以上是关于元组(TupleValueTuple)的主要内容,如果未能解决你的问题,请参考以下文章

Python:元组列表:比较所有元组并检索元组的元素不等于任何其他元组的元组

Python数据类型 ——— 元组

关于python的元组操作

好好学python · 元组

python容器--元组

python容器--元组