返回两个值,Tuple vs'out'和'struct'

考虑一个返回两个值的函数。 我们可以写:

// Using out: string MyFunction(string input, out int count) // Using Tuple class: Tuple<string, int> MyFunction(string input) // Using struct: MyStruct MyFunction(string input) 

哪一个是最佳实践,为什么?

他们各有利弊。

输出参数是快速和便宜的,但要求你通过一个variables,并依靠突变。 用LINQ正确使用out参数几乎是不可能的。

元组使收集压力和非自我logging。 “Item1”不是很具描述性。

如果定制结构很大,定制结构的拷贝速度可能会很慢,但是如果它们很小,则可以自我logging并且效率很高。 然而,定义一堆用于微不足道的用途的定制结构也是一件痛苦的事情。

我会倾向于定制结构解决scheme所有其他的东西是平等的。 更好的办法是做一个只返回一个值的函数 。 为什么你首先返回两个值?

更新:请注意,C#7中的元组在本文撰写六年后出货,是值types,因此不太可能产生收集压力。

我认为答案取决于函数在做什么的语义以及两个值之间的关系。

例如, TryParse方法使用out参数来接受parsing的值,并返回一个bool来指示parsing是否成功。 这两个值并不真正属于一个整体,所以从语义上讲,它更有意义,代码的意图更容易阅读,使用out参数。

但是,如果函数返回屏幕上某个对象的X / Y坐标,那么这两个值在语义上属于一个整体,最好使用一个struct

我个人避免使用一个tuple来获取外部代码可见的任何东西,因为检索成员的尴尬语法。

除了以前的答案,C#7带来了值types元组,不像System.Tuple是一个引用types,也提供了改进的语义。

你仍然可以让它们不被命名并使用.Item*语法:

 (string, string, int) getPerson() { return ("John", "Doe", 42); } var person = getPerson(); person.Item1; //John person.Item2; //Doe person.Item3; //42 

但是这个新特性的真正强大之处在于具有命名元组的能力。 所以我们可以像这样重写上面的内容:

 (string FirstName, string LastName, int Age) getPerson() { return ("John", "Doe", 42); } var person = getPerson(); person.FirstName; //John person.LastName; //Doe person.Age; //42 

解构也支持:

(string firstName, string lastName, int age) = getPerson()

我将采用使用Out参数的方法,因为在第二种方法中,您需要创buildTuple类的对象,然后为其添加值,与在out参数中返回值相比,我认为这是一个代价高昂的操作。 虽然如果你想在Tuple类中返回多个值(事实上不能通过返回一个输出参数来实现),那么我将采用第二种方法。

你没有提到另外一个选项,它有一个自定义类而不是struct。 如果数据具有与其相关的语义,可以通过函数对其进行操作,或者实例大小足够大(按照经验法则大于16个字节),则自定义类可能是首选。 在公共API中不推荐使用“out”,因为它与指针相关联,并且需要了解引用types的工作原理。

https://msdn.microsoft.com/en-us/library/ms182131.aspx

元组适合内部使用,但在公共API中使用起来很尴尬。 所以,我的投票是公共API的结构和类之间。

没有“最佳实践”。 这是你所熟悉的,什么在你的情况下效果最好。 只要你符合这一点,你发布的任何解决scheme都没有问题。