在开发的过程中经常遇到需要返回多个值的情况,有时候返回的值是一组相关的信息,比如,获取一个人的年龄和身高,通常应该定义一个类来接收返回的信息,但直接返回更方便。有时,一个方法可能只是校验是否符合条件,同时返回额外的信息。
Out关键字
我们在学习C#基础时,就已经知道了 out关键字。所以针对上面第二种情况可以使用out关键字来实现,如下面代码所示
static bool Check(out long timestamp)
{
timestamp = new DateTimeOffset(DateTime.Now).ToUnixTimeMilliseconds();
return true;
}
上面的代码只作为演示,没有实际意义。Check方法需要返回一个布尔值,同时需要接收内部返回的一个时间戳。
Tuple
上面的方法还可以使用Tuple来实现,代码如下
static Tuple<bool, long> Check()
{
var timestamp = new DateTimeOffset(DateTime.Now).ToUnixTimeMilliseconds();
return new Tuple<bool, long>(true, timestamp);
}
使用Tuple返回的结果,只能使用 Item1 , Item2 的形式访问,上面的例子中 Item1 代表检查结果,Item2 表示时间戳。从形式上来看不够优雅,而且使用Check方法时对返回的结果不易理解。
那么有没有好的办法呢?当然有,那就是ValueTuple。
ValueTuple
ValueTuple是在C# 7中引入的,它继承自 ValueType ,所以ValueTuple 是一个值类型,它的数据成员,如 Item1,Item2是字段而不是属性。使用ValueTuple实现上面的方法,如下:
static ValueTuple Check()
{
var timestamp = new DateTimeOffset(DateTime.Now).ToUnixTimeMilliseconds();
return new ValueTuple(true, timestamp);
}
这个跟使用Tuple一样,也是使用 Item1,Item2这样的形式获取结果。但是它有语法糖,也是优雅的地方。上面的方法还可以这样写
static (bool result, long timestamp) Check()
{
var timestamp = new DateTimeOffset(DateTime.Now).ToUnixTimeMilliseconds();
return (true, timestamp);
}
如下调用Check
var checkResult = Check();
Console.WriteLine(checkResult.result);
Console.WriteLine(checkResult.timestamp);
或者
(bool result, long timestamp) = Check();
Console.WriteLine(result);
Console.WriteLine(timestamp);
或者
var (result, timestamp) = Check();
Console.WriteLine(result);
Console.WriteLine(timestamp);
是不是很优雅。
结语
本篇文章通过简单的比较 out,Tuple 和 ValueTuple 的写法,展示了 ValueTuple的好处,并没有深入介绍。同时有一些地方,比如序列化时需要注意,这不在本篇讨论的范围,可以参考相关内容。