返回两个值,Tuple vs'out'vs'truct'

时间:2011-06-17 06:01:53

标签: c# struct tuples out value-type

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

// Using out:
string MyFunction(string input, out int count)

// Using Tuple class:
Tuple<string, int> MyFunction(string input)

// Using struct:
MyStruct MyFunction(string input)

哪一个是最佳做法?为什么?

6 个答案:

答案 0 :(得分:81)

他们各有利弊。

Out参数快速且便宜,但要求您传入变量,并依赖于变异。几乎不可能在LINQ中正确使用out参数。

元组会产生收集压力,并且是非自我记录的。 “Item1”不是很具描述性。

如果自定义结构很大,则复制速度很慢,但是它们是自我文档的,如果它们很小则效率很高。然而,为琐碎的用途定义一大堆自定义结构也是一件痛苦的事。

我倾向于自定义结构解决方案所有其他条件相同。更好的方法是创建一个只返回一个值的函数。你为什么要首先返回两个值?

更新:请注意,编写本文六年后发布的C#7中的元组是值类型,因此不太可能产生收集压力。

答案 1 :(得分:19)

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

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

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

我个人避免使用tuple来查看外部代码可见的任何内容,因为检索成员的方法很笨拙。

答案 2 :(得分:15)

除了之前的答案之外,C#7还带来了值类型元组,与System.Tuple不同,它是一种引用类型,并且还提供了改进的语义。

您仍然可以将其保留为未命名,并使用.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()

答案 3 :(得分:1)

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

答案 4 :(得分:1)

You did not mention one more option, which is having a custom class instead of struct. If the data has semantics associated to it which can be operated upon by functions, or the instance size is big enough (> 16 bytes as a rule of thumb), a custom class may be preferred. Use of "out" is not recommended in public API because of its association to pointers and requiring understanding of how reference types work.

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

Tuple is good for internal use, but it usage is awkward in public API. So, my vote is between struct and class for public API.

答案 5 :(得分:0)

没有“最佳做法”。这是你感到舒服的,在你的情况下最有效的。只要您与此保持一致,您发布的任何解决方案都没有问题。