栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

System.ValueTuple和System.Tuple有什么区别?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

System.ValueTuple和System.Tuple有什么区别?

是什么

ValueTuples
,为什么不
Tuple
呢?

A

ValueTuple
是反映元组的结构,与原始
System.Tuple
类相同。

Tuple
和之间的主要区别
ValueTuple
是:

  • System.ValueTuple
    是值类型(结构),
    System.Tuple
    而是引用类型(
    class
    )。在谈论分配和GC压力时,这是有意义的。
  • System.ValueTuple
    不仅是一个
    struct
    ,而且是 可变 的,因此在使用它们时一定要小心。想一想当一个类拥有一个
    System.ValueTuple
    as字段时会发生什么。
  • System.ValueTuple
    通过字段而不是属性公开其项目。

在C#7之前,使用元组还不是很方便。它们的字段名称是

Item1
Item2
等,并且该语言没有像大多数其他语言(Python,Scala)那样为它们提供语法糖。

当.NET语言设计团队决定合并元组并在语言级别向其添加语法糖时,一个重要因素就是性能。随着

ValueTuple
是值类型,你可以使用它们,因为(作为一个实现细节)时,为了避免GC压力,他们会在栈上分配。

另外,

struct
运行时会获得自动(浅)等式语义,而运行时
class
不会。尽管设计团队确保为元组提供了更加优化的相等性,但因此为其实现了自定义相等性。

这是以下设计注释中

Tuples
的一段:

结构或类:

如前所述,我建议创建元组类型

structs
而不是
classes
,这样就不会与它们相关联的分配罚款。它们应尽可能轻巧。

可以说,

structs
最终可能会导致成本更高,因为分配复制了更大的价值。因此,如果分配给它们的权限远远大于创建的权限,那么
structs
这将是一个错误的选择。

但是,在其动机中,元组是短暂的。当部分比整体重要时,您将使用它们。因此,常见的模式是构造,返回并立即对其进行解构。在这种情况下,结构显然是更可取的。

结构还具有许多其他好处,这在下面将变得显而易见。

例子:

您可以很容易地看到,使用它

System.Tuple
很快就会变得模棱两可。例如,假设我们有一种计算a的总和和计数的方法
List<Int>

public Tuple<int, int> DoStuff(IEnumerable<int> values){    var sum = 0;    var count = 0;    foreach (var value in values) { sum += value; count++; }    return new Tuple(sum, count);}

在接收端,我们最终得到:

Tuple<int, int> result = DoStuff(Enumerable.Range(0, 10));// What is Item1 and what is Item2?// Which one is the sum and which is the count?Console.WriteLine(result.Item1);Console.WriteLine(result.Item2);

您可以将值元组解构为命名参数的方法是该功能的强大功能:

public (int sum, int count) DoStuff(IEnumerable<int> values) {    var res = (sum: 0, count: 0);    foreach (var value in values) { res.sum += value; res.count++; }    return res;}

在接收端:

var result = DoStuff(Enumerable.Range(0, 10));Console.WriteLine($"Sum: {result.Sum}, Count: {result.Count}");

要么:

var (sum, count) = DoStuff(Enumerable.Range(0, 10));Console.WriteLine($"Sum: {sum}, Count: {count}");

编译器好东西:

如果我们看一下先前示例的内容,

ValueTuple
当我们要求其解构时,我们可以确切地看到编译器的解释方式:

[return: TupleElementNames(new string[] {    "sum",    "count"})]public ValueTuple<int, int> DoStuff(IEnumerable<int> values){    ValueTuple<int, int> result;    result..ctor(0, 0);    foreach (int current in values)    {        result.Item1 += current;        result.Item2++;    }    return result;}public void Foo(){    ValueTuple<int, int> expr_0E = this.DoStuff(Enumerable.Range(0, 10));    int item = expr_0E.Item1;    int arg_1A_0 = expr_0E.Item2;}

在内部,编译后的代码使用

Item1
Item2
,但是由于我们使用的是分解的元组,因此所有这些都从我们这里抽象出来。具有命名实参的元组用注释
TupleElementNamesAttribute
。如果我们使用单个新鲜变量而不是分解,则会得到:

public void Foo(){    ValueTuple<int, int> valueTuple = this.DoStuff(Enumerable.Range(0, 10));    Console.WriteLine(string.Format("Sum: {0}, Count: {1})", valueTuple.Item1, valueTuple.Item2));}

请注意,编译器仍然必须作出一些魔术发生(通过属性),当我们调试我们的应用程序,因为这将是奇怪地看到

Item1
Item2



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/421430.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号