使用泛型元组替代out与ref形式传参
我们在开发的时候,都会常常遇到一个问题,如何为逻辑上返回多个对象设计方法签名。通常我们会想到使用out或ref修饰参数,或者麻烦些自己设定一个类型内部包含多个Object类型属性来接收多个返回值。这两中方式都不够好,前者让程序难以实现多态(out或ref修饰的参数类型,不能使用派生类替代),设计走向是面向过程,也难以使用链式编程;后者因为所有的返回都Object类型,所以在使用时都要进行转换成真实的类型。在这种情况下我们可以使用泛型元组类型来处。在.Net 4.0中新增了Tuple与Tuple<T1>、Tuple<T1,T2>、Tuple<T1,......,T7,TRest>。就解决了上面的问题。
其泛型元组可以更好的处理4种情况:
①替代out与ref修饰的参数(即方法含有多个返回值)。
②通过单个参数将多个值传递给一个方法。例如, Thread.Start(Object) 方法有一个单一参数,可以使用该参数向在启动时线程执行的方法提供一个值。
③提供对数据集的轻松访问和操作。如一条数据(Tuple)中含有多个子数据(Tuple中属性),多条记录合并成了数据集(类型为Tuple的集合)。
④表示一组数据。例如,元组可以表示数据库中的一条记录,并且其属性可以表示该记录的字段。
如下:展示了一个泛型Tuple的声明
public class Tuple<T1, T2, T3> : IStructuralEquatable, IStructuralComparable, IComparable { public Tuple(T1 item1, T2 item2, T3 item3); public T1 Item1 { get; } public T2 Item2 { get; } public T3 Item3 { get; } //省略方法的具体实现 public override bool Equals(object obj); public override int GetHashCode(); public override string ToString(); //省略对借口的实现 }
在.Net4.0以下的版本虽然没有框架自带的泛型元组,但是我们可以自己定义泛型元组(代码结构如上),其类型中的比较与相等的接口也可以根据需要是否实现。
如下分别为out或ref修饰参数使用、泛型元组Tuple<T1,T2>的使用
public static float TemperatureOfCity(string cityId, out string cityName) { //省略数据处理内容 cityName = "腾冲"; float temperature = 23.6f; return temperature; } public static Tuple<string, float> TemperatureOfCity(string cityId) { //省略数据处理内容 string cityName = "腾冲"; float temperature = 23.6f; return new Tuple<string, float>(cityName, temperature); }
可能你并不希望此类Tuple的定义扰乱了类型的真正含义,好在C#的设计者也考略到这个问题,允许我们使用using语句为任意的封闭泛型类型声明一个别名。
using CityTemperature = Tuple<string, float>; public static Tuple<string, float> TemperatureOfCity(string cityId) { //省略数据处理内容 string cityName = "腾冲"; float temperature = 23.6f; return new CityTemperature(cityName, temperature); }
以上虽然只详细的列出了泛型元组处理的4中情况的(替代out或ref参数)一种,但是其他3中情况的代码编写都是类似。就不一一明细列出。