哪个更好,返回值还是输出参数?

如果我们想从一个方法中获得一个值,我们可以使用如下的返回值:

public int GetValue(); 

要么:

 public void GetValue(out int x); 

我不是很了解他们之间的差异,所以不知道哪个更好。 你能解释一下吗?

谢谢。

当方法没有其他东西要返回时,返回值几乎总是正确的select。 (事实上​​,如果我有select的话,我想不出任何一个带有out参数的void方法,C#7的Deconstruct方法对于语言支持的解构来说是非常非常罕见的例外这个规则。)

除了别的之外,它会阻止调用者分别声明variables:

 int foo; GetValue(out foo); 

VS

 int foo = GetValue(); 

Out值也阻止了这样的方法链接:

 Console.WriteLine(GetValue().ToString("g")); 

(事实上​​,这也是属性设置器的问题之一,这也是为什么构build器模式使用返回构build器的方法,例如myStringBuilder.Append(xxx).Append(yyy) 。)

此外,out参数稍微难以用于reflection,通常也会使testing更加困难。 (更多的努力通常会让模拟返回值比输出参数容易)。 基本上没有什么我能想到的,他们变得更容易

返回值FTW。

编辑:根据发生了什么事…

基本上当你传入一个“out”参数的参数时,你必须传入一个variables。 (数组元素也被分类为variables。)您调用的方法在其堆栈中没有“new”variables,它使用variables进行存储。 variables中的任何更改都立即可见。 以下是一个显示差异的例子:

 using System; class Test { static int value; static void ShowValue(string description) { Console.WriteLine(description + value); } static void Main() { Console.WriteLine("Return value test..."); value = 5; value = ReturnValue(); ShowValue("Value after ReturnValue(): "); value = 5; Console.WriteLine("Out parameter test..."); OutParameter(out value); ShowValue("Value after OutParameter(): "); } static int ReturnValue() { ShowValue("ReturnValue (pre): "); int tmp = 10; ShowValue("ReturnValue (post): "); return tmp; } static void OutParameter(out int tmp) { ShowValue("OutParameter (pre): "); tmp = 10; ShowValue("OutParameter (post): "); } } 

结果:

 Return value test... ReturnValue (pre): 5 ReturnValue (post): 5 Value after ReturnValue(): 10 Out parameter test... OutParameter (pre): 5 OutParameter (post): 10 Value after OutParameter(): 10 

不同的是在“后”步骤 – 即局部variables或参数已被改变之后。 在ReturnValuetesting中,这对静态valuevariables没有任何影响。 在OutParametertesting中, valuevariables由行tmp = 10;更改tmp = 10;

你通常应该更喜欢一个外部参数的返回值。 如果你发现自己写代码需要做两件事情,那么这个params就是一个神秘的邪恶。 一个很好的例子就是Try模式(比如Int32.TryParse)。

让我们来考虑你的两个方法的调用者将不得不做什么。 对于第一个例子,我可以写这个…

 int foo = GetValue(); 

请注意,我可以声明一个variables,并通过您的方法将其分配在一行中。 在第二个例子中,它看起来像这样…

 int foo; GetValue(out foo); 

我现在不得不先声明我的variables,然后用两行写我的代码。

更新

问这些types的问题时,一个好的地方是.NET框架devise指南。 如果你有这本书的版本,那么你可以看到Anders Hejlsberg和其他人在这个主题上的注释(第184-185页),但是在线版本在这里…

http://msdn.microsoft.com/en-us/library/ms182131(VS.80).aspx

如果你发现自己需要从一个API中返回两件事情,那么把它们包装在一个结构体/类中将比一个出来的参数更好。

什么更好,取决于你的具体情况。 存在的原因之一是为了便于从一个方法调用返回多个值:

 public int ReturnMultiple(int input, out int output1, out int output2) { output1 = input + 1; output2 = input + 2; return input; } 

所以一个在定义上并不比另一个更好。 但是,通常情况下,您会希望使用简单的回报,除非您有上述情况。

编辑:这是一个示例演示关键字存在的原因之一。 以上决不被视为最佳做法。

有一个理由使用一个尚未提及的out参数:调用方法有义务接收它。 如果你的方法产生了一个值,这个呼叫者不应该丢弃,使得呼叫者明确地接受它:

  Method1(); // Return values can be discard quite easily, even accidentally int resultCode; Method2(out resultCode); // Out params are a little harder to ignore 

当然,调用者仍然可以忽略out参数中的 ,但是您已经注意到了这一点。

这是一个罕见的需求; 更经常的情况是,你应该为真正的问题使用例外,或者返回一个包含“供参考”状态信息的对象,但是在某些情况下这很重要。

主要是偏好

我更喜欢回报,如果你有多个回报,你可以把它们包装在一个Result DTO中

 public class Result{ public Person Person {get;set;} public int Sum {get;set;} } 

你应该几乎总是使用返回值。 “ out ”参数会对许多API,组合性等造成一些摩擦。

最值得注意的例外是当你想要返回多个值(.Net框架直到4.0时才有元组),比如TryParse模式。

您只能有一个返回值,而您可以有多个输出参数。

在这些情况下,您只需要考虑参数。

但是,如果您需要从方法中返回多个参数,则可能需要查看从OO方法返回的内容,并考虑是否最好使用这些参数返回对象或结构。 所以你又回到了返回值。

我宁愿在这个简单的例子中,而不是其中任何一个。

 public int Value { get; private set; } 

但是,他们都非常相似。 通常,如果需要从方法中传回多个值,则只能使用“out”。 如果你想发送一个值进出该方法,可以select'ref'。 我的方法是最好的,如果你只是返回一个值,但如果你想传递一个参数,并返回一个值可能会select你的第一select。

它们都有不同的目的,编译器也不会这样做。 如果你的方法需要返回一个值,那么你必须使用return。 Out用于你的方法需要返回多个值的地方。

如果你使用return,那么数据首先被写入方法栈,然后写入调用方法。 在out的情况下,它直接写入调用方法堆栈。 不知道是否有更多的差异。

没有真正的区别,out参数在C#中允许方法返回多于一个值,即所有。

然而,有一些细微的差异,但非他们是非常重要的:

使用out参数将强制你使用两行:

 int n; GetValue(n); 

而使用返回值会让你在一行中做到这一点:

 int n = GetValue(); 

另一个区别(只适用于值types,只有在C#不内联函数时)是使用返回值必须在使用OUT参数时返回的函数不一定是这个值的副本。

正如其他人所说:返回值,不是出来参数。

我可以向你推荐“框架devise指南”(第二版)吗? 第184-185页介绍了避免参数的原因。 整本书将引导你在各种.NET编码问题上的正确方向。

与框架devise指南结合使用的是静态分析工具FxCop。 你可以在微软的网站上免费下载。 在你编译的代码上运行这个,看看它说什么。 如果它抱怨成千上万的事情…不要惊慌! 仔细看看每个案例的说话。 不要急于尽快解决问题。 学习它告诉你什么。 你将会走上掌握之路。

我认为在less数情况下,有用的方法之一是使用非托pipe内存,并且希望显而易见的是应该手动处理“返回”值,而不是期望它自己处理。

另外,返回值与asynchronousdevise范例兼容。

如果使用ref或out参数,则不能指定函数“async”。

总而言之, 返回值允许方法链接,更清晰的语法(通过消除调用者声明附加variables的必要性),并允许asynchronousdevise,而不需要在将来进行实质性修改。

当您试图返回您在方法中声明的对象时,out更有用。

 public BookList Find(string key) { BookList book; //BookList is a model class _books.TryGetValue(key, out book) //_books is a concurrent dictionary //TryGetValue gets an item with matching key and returns it into book. return book; } 

返回值是您的方法返回的正常值。

out参数中,out和ref是C#的两个关键字,它们允许传递variables作为参考

refout之间的最大区别是, ref应该在之前和之后初始化

使用返回types为bool的out关键字有时可以减less代码膨胀并提高可读性。 (主要是当外部参数中的额外信息经常被忽略。)例如:

 var result = DoThing(); if (result.Success) { result = DoOtherThing() if (result.Success) { result = DoFinalThing() if (result.Success) { success = true; } } } 

VS:

 var result; if (DoThing(out result)) { if (DoOtherThing(out result)) { if (DoFinalThing(out result)) { success = true; } } }