C#的未来:元组及匿名结构体

2015 年 5 月 07 日

随着 C# 6 接近完成,C# 7 的开发计划也开始提到了日程上。虽然目前为止,还没有任何可确定的内容,但 C#团队已经开始按照“兴趣及预计可行性”将各种提议进行分类。在这个系列文章中,我们将对某些提议进行分析,首先从对元组的语言支持开始。

使用元组的目标是以一种轻量级的方式从一个函数中返回多个值。对元组的良好支持能够消除对out 参数的使用,这种参数通常被认为是一种笨重的方案。此外,out 参数无法兼容async/await,因此在许多场景中out 参数将变得毫无作用。

元组类存在什么问题?

从.NET Framework 4 开始,就加入了Tuple(元组)这个类。但是多数开发者都认为这个类只在非常有限的场景中才能够体现出实用性。首先,元组是一个类,这意味着在使用时必须为它分配内存,而这一点会增加内存的压力,并使垃圾回收器的执行周期变得更加频繁。如果要让元组与out 参数在性能方面进行竞争,需要将其实现为一个结构体。

第二个问题与API 的设计有关,如果你看到了某个返回类型Tuple<int, int>,那么从类型本身你无法了解任何信息。如此一来,在使用这个函数的过程中你至少需要检查文档两次,一次是在编写函数时,另一次则是在代码审查时。如果返回类型能够表现为类似于Tuple<int count, int sum> 这样,那么它的实用性将会大大增加。

匿名结构体

考虑一下以下代码:

public (int sum, int count) Tally(IEnumerable values) { … }
var t = new (int sum, int count) { sum = 0, count = 0 };

在这条提议中,以上每一行代码都将定义一个新的匿名值类型,其中包括 sum 和 count 属性。需要注意的是,和匿名类不同,匿名结构体要求你明确地列举出属性的名称与类型。

使用结构体的一个好处在于它们会自动定义 Equals 和 GetHashCode 方法。不过也有人会表示默认的实现方式不够高效,编译器应当替换它的实现。

分解元组

关于元组的提议中有一个重要的部分,即应当能够通过一行代码对元组进行分解。考虑一下下面的代码块:

var t = Tally(myValues);
var sum = t.Sum;
var count = t.Count;

使用分解功能,这段代码就能够进行简化:

(var sum, var count) = Tally(myValues);

目前还没有决定是否能够在不定义新变量的提前下对元组进行分组。或者换句话说,能否省略“var”的使用,而代之以某个已经存在的本地变量。

返回元组

关于如何从某个函数中返回元组类型这一点,有两条提议正在考虑中。第一条提议非常容易理解:

return (a, b);

而第二条提议的方式将完全不使用 return 语句。考虑一下这个示例:

public (int sum, int count) Tally(IEnumerable values)
{
sum = 0; count = 0;
foreach (var value in values) { sum += value; count++; }
}

隐式创建的本地及返回变量并不是一种新的概念,Visual Basic 最初的设计就是这样的,只是在 VB 7 中引入了返回语句之后,这种方法才逐渐变得不流行了。这种写法也类似于使用 out 参数的方式。不过,对于许多开发者来说,在函数中看不到返回语句总是让他们感觉有些不安。

其它问题

对元组的支持是一个比看上去还要复杂的主题。虽然本文目前讨论的主要是日常的使用方式,但还有许多细节需要从编译器的作者以及高级使用场景的角度进行处理。

元组是否应该作为可变类型?从性能及便利性的角度考虑,这种选择具有一定实用性,但这有可能让代码变得更容易出错,尤其是在处理多线程的情况下。

元组是否应该跨多个程度集进行统一化?匿名类型并不是统一的,但元组与匿名类型不同,它们可以作为 API 的一部分向外部暴露。

元组能否被转型为其它元组?表面上看,如果两个元组具有相同的类型结构,但具有不同的属性名称。或者具有相同的属性名称,但属性的类型更宽泛,那么这种转换应该是可以接受的。

如果你将某个具有两个值的元组作为参数传递给某个接受两个参数的函数,那么是否应该将元组进行自动分解(摊平)呢?反过来,你能够“反分解”某个参数对,将其合并为某个元组参数吗?

查看英文原文: C# Futures: Tuples and Anonymous Structs

2015 年 5 月 07 日 10:011624
用户头像

发布了 428 篇内容, 共 148.0 次阅读, 收获喜欢 20 次。

关注

评论

发布
暂无评论
发现更多内容

week7 性能优化(一) 作业和学习总结

杨斌

极客时间架构 1 期:第 12 周 数据应用(一) - 命题作业

Null

HiveQL分析

天天向上

极客大学架构师训练营

大数据应用总结一

天天向上

极客大学架构师训练营

极客大学 - 架构师训练营 第十二周作业

9527

架構師訓練營 week12 作業

ilake

架构师训练营—第十二周学习总结

Geek_shu1988

hashmap 是如何炼成的

哈希说

数据结构

架构师训练营 week8 学习总结

花果山

极客大学架构师训练营

【第十二周】数据应用

云龙

「架构师训练营第 1 期」第十二周作业

张国荣

架构师训练营第 1 期第 12 周作业

好吃不贵

极客大学架构师训练营

链表合并问题

jorden wang

第十二周

Geek_ce484f

极客大学架构师训练营

第十二周 数据应用(一)作业

钟杰

极客大学架构师训练营

第十二周 数据应用(一)

9527

架构师训练营第 8 周课后练习

菜青虫

极客大学架构师训练营

架构师训练营第 8 周学习总结

菜青虫

极客大学架构师训练营

【架构师训练营第 1 期 12 周】 作业

Bear在挨踢

极客大学架构师训练营

周练习 12

何毅曦

架构师训练营第 11 周课后练习

week8性能优化(二)作业和学习总结

杨斌

第三周学习总结

J

极客大学架构师训练营

TronChain波场链系统APP开发|TronChain波场链软件开发

开發I852946OIIO

系统开发

【架构师训练营第 1 期 12 周】 学习总结

Bear在挨踢

极客大学架构师训练营

极客时间架构 1 期:第 12 周 数据应用(一) - 学习总结

Null

架构之书:出路与《Expert One-on-One J2EE Development without EJB》

lidaobing

Java 架构

架构师训练营—第十二周作业

Geek_shu1988

用户观看视频业务出现花屏故障

网络技术平台

架构师训练营第 12 周课后练习

训练营第十二周作业 1

仲夏

C#的未来:元组及匿名结构体-InfoQ