问题:
在许多情况下,从一个方法返回一个值是不够的。你需要一种方式来从一个方法返回不止一个数据项。
解决方案:
1、对充当返回参数的参数使用关键字out。下面的方法接受一个InputShape参数,并通过该值计算height、width和depth
public void ReturnDimensions(int inputShape, out int height, out int width, out int depth)
{
height = 0; width = 0; depth = 0;
// 通过inputShape值计算height width和depth
}
这个方法以如下方式进行调用:
// 声明输出参数
int height;
int width;
int depth;
// 调用方法并返回height width和depth
Obj.ReturnDimensions(1, out height, out width, out depth);
2、另一个方法将返回一个包含所有返回值的类或结构。
修改前一个方法,使其返回一个结构,而不是使用out参数:
public Dimensions ReturnDimensions(int inputShape)
{ // 默认构造函数自动将结构的成员初始化为0
Dimensions objDim = new Dimensions();
// 通过inputShape的值计算objDim.Height objDim.WidthobjDim.Depth
return objDim;
}
//其中 Dimensions 的下。
public struct Dimensions
{
public int Height;
public int Width;
public int Depth;
}
现在以如下方式调用这个方法。
// 调用方法并且返回height、width和depth
Dimensions objDim = obj.ReturnDimensions(1);
3、除了从此方法返回一个用户定义的类或结构,也可以用一个Tuple对象包含所有的返回值。
修改前一个方法,使其返回一个Tuple。
public Tuple<int, int, int> ReturnDimensionsAsTuple(int inputShape)
{ // inputShape值objDim.Height objDim.WidthobjDim.Depth // 例如{5, 10, 15}
// 一个包含的值的Tuple
var objDim = Tuple.Create<int, int, int>(5, 10, 15);
return (objDim);
}
// 现在以如下方法调用这个方法
// 调用方法并且返回height、width和depth
Tuple<int, int, int> objDim = obj.ReturnDimensions(1);
讨论:
在方法签名中使用out关键字创建一个参数,指示这个参数将由该方法初始化并返回。当需要方法返回多个值时,这个技巧就很好用。一个方法最多只能有一个返回值,但是通过使用out关键字,可以把多个参数标记为一个返回值。
你可能想知道为什么不能使用ref参数代替out参数,鉴于他们都允许一个方法改变像这样标记的参数的值。答案是,out参数使代码有些自文档化。当遇到一个out参数时,你知道这个参数充当一个返回值。此外,在把out参数传入方法之前,不需要做额外的工作来初始化它;而ref参数则需要这样做。
(注:在调用方法时不需要对out参数进行封送;相反,在方法把数据返回给调用者时对其封送一次。任何其他调用类型(按值调用或者使用ref关键字按引用调用)都要求在两个方向上对值进行封送。在封送场合下使用out关键字可以改进远程调用性能。
在仅有少量值需要返回时,out参数是非常有用的;但是当你遇到需要返回4、5、6个甚至更多的值时,他就变得笨重了。另外一个返回多个值的选项时创建并返回用户自定义的类或结构,或者使用Tuple打包需要由某个方法返回的所有值。
与用户自定义的对象相比,使用Tuple更加简洁。可以创建一个Tuple,用于包含不同类型的任意数量的值。此外,Tuple中保存的数据是不可变的;一旦通过构造函数或者静态的Create方法将数据添加到Tuple中,就无法再修改这些数据了。
Tuple可以接受包含8个独立的值。如果你需要8个以上的值,那么需要使用这个特别的类:
Tuple<T1, T2, T3, T4, T5, T6, T7, TRest> Class
参考:
MSDN文档中的“Tuple 类”和“Tuple<T1, T2, T3, T4, T5, T6, T7, TRest> 类”主题