前言

元组并不是c# 7.0的东西,早之前就有,叫做tuple。7.0加了valuetuple。

来看下元组吧,主要一些注意的地方。

正文

为什么在7.0 之前,元组用的不多呢?

因为tuple 在代码优雅上和阅读上存在很大的问题,因为有匿名类型,是一个鸡肋的存在。

Tuple,翻译过来是元组的意思,元组听到这个词,一般会想到两个特性,一个是不可扩展,一个是顺序已定。

这种的确灵活性不高,这并不是一个贬义词。灵活性不高表示其稳定。

static void Main(string[] args)
{
Tuple<int, int> a = Tuple.Create(1, 2);
var b= a.Item1;
var c = a.Item2; Console.ReadKey();
}

当看到这个代码的第一眼,是不是有一种坏味道的感觉?

理由也很简单,a.Item1 含义是什么,这是调用者费解的问题。

这里完全可以用匿名类型替换。

那么是否匿名类型是否能完全替代元组呢?不能。

public static Tuple<int, int> Divide (int dividend, int divisor)
{
int result = dividend / divisor;
int remainder = dividend % divisor; return Tuple.Create( result, remainder );
}

因为元组可以作为方法的返回值。所以元组在内部方法的时候还是可以用一下的(因为内部更能知道其具体的实现目标),不用声明新的模型,但是对胃不好。

像下面这样:

这样作为内部方法。那么如果放在方面会有什么感觉呢?感受一下。

那么就是main需要事先知道"外部"的信息,item1是name,item2是age。其他内调用的也需要知道,使用的成本就更高了。如果是public外部调用,那么味道就更重了。

前面提及到其稳定,那么其稳定表现到什么地方呢?

不能被修改。这并不是缺陷,相反这是一个特性。

因为元组不可修改,代表其稳定,当使用元组的时候就不用考虑其是否修改,这个在后面设计篇的时候会介绍下稳定性的好处。

简单看下create,其还是可以嵌套元组的。

不用纠结太多,在7.0之前元组基本只有这点用处。地位有点尴尬,感觉像是对匿名类型的补充。

那么到了7.0之后呢? 增加了ValueTuple。

ValueTuple是C# 7.0的新特性之一,.Net Framework 4.7以上版本可用。

  1. 值元组也是一种数据结构,用于表示特定数量和元素序列,但是是和元组类不一样的,主要区别如下:

    值元组是结构,是值类型,不是类,而元组(Tuple)是类,引用类型;值元组的数据成员是字段不是属性,所以建议小写。
  2. 值元组元素是可变的,不是只读的,也就是说可以改变值元组中的元素值;

优化:当构造出超过7个元素以上的值元组后,可以使用接下来的ItemX进行访问嵌套元组中的值,对于上面的例子,要访问第十个元素,既可以通过testTuple10.Rest.Item3访问,也可以通过testTuple10.Item10来访问。

前面这个算不上优化的地方,因为一般不会超过7个,如果超过7个,那么其具备某种含义,应该建模,创建类。

关于4.6以下需要使用。 4.7内置,4.0以上NuGet能直接装System.ValueType包

前面其主要是诟病的地方是过于抽象(使用item1这种名称),第二个是创建繁琐,需要Tuple.create(),那么在这个版本就解决了这种问题。

static void Main(string[] args)
{
var student = GetStudentInfo1();
var age = student.age; Console.ReadKey();
} static (string name, int age, uint height) GetStudentInfo1()
{
return ("Bob", 28, 175);
}

不仅解决了创建和使用的问题,还增加了一些新的特性。

上面这种var student = GetStudentInfo1(),一般不建议这么写的。

因为(string name, int age, uint height)并不能代表student,这种学生模型。

元组是一些数值的组合,并不能替代模型。

static void Main(string[] args)
{
var (name, age, hight) = GetStudentInfo1(); Console.ReadKey();
} static (string name, int age, uint height) GetStudentInfo1()
{
return ("Bob", 28, 175);
}

写法上更希望是上面这种,表示的是一些数值的组合。

那么其设计也有弃元这个东西,因为可能只使用了其中的一部分。

internal class Program
{
static void Main(string[] args)
{
var (_, age, _) = GetStudentInfo1(); Console.ReadKey();
} static (string name, int age, uint height) GetStudentInfo1()
{
return ("Bob", 28, 175);
}
}

最后一个关键的点,那就是前面能实现这些:

static (string name, int age, uint height) GetStudentInfo1()
{
return ("Bob", 28, 175);
}
var (name, age, hight) = GetStudentInfo1();
var (_, age, _) = GetStudentInfo1();

统统都是语法糖。

并不是ValueTuple 这么强大,而是编译器工具强大了。

你发现跟原来区别不大:

然后其实这些name啊,age啊,height啊,在运行时候ValueTuple也没有。

他们在ValueTuple 还是item1,item2,item3。

var a = ("Bob", 28, 175);
var output =JsonConvert.SerializeObject(a); Console.WriteLine(output);
Console.ReadKey();

所以不要吧什么元组直接返回给ActionResult,那么得到的结果是item1,item2这种,因为编译后运行的时候调用就会把具体名称缓存item1和item2,这和匿名类型是不同的,匿名类型是编译会生成具体的类。

说一下在设计上值得注意的地方,就是元组应该是类内部使用。

为什么这么说呢?

因为成本问题,比如说:

static (string name, int age, uint height) GetStudentInfo1()
{
return ("Bob", 28, 175);
}

对于外部类来说,其实就是返回多个值,并没有具体的对象含义。

不像是下面这种:

static Student GetStudentInfo1()
{
return db.getStudent();
}

其最大的使用范围其实就是类的内部,内部方法是最佳场景,当然其在本身实现上没有限制。

因为这个元组有很多个人看法在里面,如有不对望请指出或者其他的不同想法也可以交流下。

最新文章

  1. 数据仓库开发——Kettle使用示例
  2. 【iCore3 双核心板_FPGA】例程六:计数器实验——计数器使用
  3. Linux中vi、vim命令大全
  4. gson 自定义对象转换格式
  5. nginx根据IP限制访问
  6. C# PDFBox 解析PDF文件
  7. [SQL] 不知道是什么存储过程
  8. Android ActionBar应用实战,高仿微信主界面的设计
  9. 初学jquery遇见的两个小问题!
  10. 搭建ganglia集群而且监视hadoop CDH4.6
  11. WPF如何获得变量异步回调函数时产生的异步回调
  12. (转)Collections类方法详解
  13. 学习 Spring (五) Aware 接口
  14. python unittest单元测试框架-3用例执行顺序、多级目录、装饰器、fixtures
  15. win7在64位系统下编译openssl
  16. R语言学习笔记—朴素贝叶斯分类
  17. C# WinForm Webbrowser 强制所有网页链接在同一页面打开或者在TabControl中弹出新窗口(续)
  18. Java进阶06 容器
  19. TX-
  20. 降低winnt Apache服务的权限,让你的虚拟主机更安全

热门文章

  1. 了解Pytorch|Get Started with PyTorch
  2. 源码学习之MyBatis的底层查询原理
  3. 关于aws账单数据中几个重要的与费用相关的字段的意义分析
  4. C++和Java多维数组声明和初始化时的区别与常见问题
  5. C语言实现扫雷游戏(完整版)
  6. 驱动开发:内核特征码扫描PE代码段
  7. 【MySQL】01_运算符、函数
  8. 第二阶段:高级核心基础知识&#183;第4章shell特性&#183;2
  9. Windows7下驱动开发与调试体系构建——5.实战反调试标记位(NtGlobalFlag)
  10. iptables和firewalld基础