如果我们想从方法中获取值,我们可以使用返回值,如下所示:
public int GetValue();
Run Code Online (Sandbox Code Playgroud)
要么:
public void GetValue(out int x);
Run Code Online (Sandbox Code Playgroud)
我真的不明白它们之间的差异,所以,不知道哪个更好.你能解释一下这个吗?
谢谢.
Jon*_*eet 151
当方法没有任何其他东西可以返回时,返回值几乎总是正确的选择.(事实上,我不能想到这里我想任何情况下,曾经想要一个空白方法与out
参数,如果我当初的选择.C#7的Deconstruct
方法语言支持的解构作为一个非常,非常罕见的例外.)
除了其他任何东西,它会阻止调用者分别声明变量:
int foo;
GetValue(out foo);
Run Code Online (Sandbox Code Playgroud)
VS
int foo = GetValue();
Run Code Online (Sandbox Code Playgroud)
Out值也会阻止方法链接,如下所示:
Console.WriteLine(GetValue().ToString("g"));
Run Code Online (Sandbox Code Playgroud)
(实际上,这也是属性设置器的问题之一,这就是构建器模式使用返回构建器的方法的原因,例如myStringBuilder.Append(xxx).Append(yyy)
.)
另外,out参数稍微难以用于反射,通常也会使测试更加困难.(通常会花费更多精力来模拟返回值而不是输出参数).基本上没有什么我能想到的,他们更容易 ......
返回值FTW.
编辑:就发生的事情而言......
基本上,当您传入一个"out"参数的参数时,您必须传入一个变量.(数组元素也被归类为变量.)您调用的方法在其堆栈上没有参数的"新"变量 - 它使用您的变量进行存储.变量中的任何更改都会立即可见.这是一个显示差异的示例:
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): ");
}
}
Run Code Online (Sandbox Code Playgroud)
结果:
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
Run Code Online (Sandbox Code Playgroud)
差异在于"后"步骤 - 即在局部变量或参数被更改之后.在ReturnValue测试中,这对静态value
变量没有影响.在OutParameter测试中,value
变量由行更改tmp = 10;
pyr*_*lus 26
什么更好,取决于您的具体情况.存在的一个原因out
是为了便于从一个方法调用返回多个值:
public int ReturnMultiple(int input, out int output1, out int output2)
{
output1 = input + 1;
output2 = input + 2;
return input;
}
Run Code Online (Sandbox Code Playgroud)
因此,根据定义,一个不是另一个.但通常你会想要使用简单的回报,除非你有上述情况.
编辑: 这是一个示例,说明关键字存在的原因之一.以上内容绝不是最佳实践.
Mar*_*eck 23
您通常应该更喜欢返回值而不是out param.如果你发现你自己编写需要做两件事的代码,那么params就是一种诡计.一个很好的例子是Try模式(例如Int32.TryParse).
让我们考虑两种方法的调用者必须做什么.对于第一个例子,我可以写这个......
int foo = GetValue();
Run Code Online (Sandbox Code Playgroud)
请注意,我可以声明一个变量,并通过您的方法在一行中分配它.对于第二个例子,它看起来像这样......
int foo;
GetValue(out foo);
Run Code Online (Sandbox Code Playgroud)
我现在被迫在前面声明我的变量并将我的代码写成两行.
更新
在询问这些类型的问题时,一个好看的地方是.NET Framework设计指南.如果您有图书版本,那么您可以看到Anders Hejlsberg和其他人关于此主题的注释(第184-185页),但在线版本在这里......
http://msdn.microsoft.com/en-us/library/ms182131(VS.80).aspx
如果你发现自己需要从API中返回两个东西,那么将它们包装在struct/class中会比out param更好.
小智 12
使用out
尚未提及的参数有一个原因:调用方法有义务接收它.如果您的方法产生一个调用者不应该丢弃的值,则out
强制调用者专门接受它:
Method1(); // Return values can be discard quite easily, even accidentally
int resultCode;
Method2(out resultCode); // Out params are a little harder to ignore
Run Code Online (Sandbox Code Playgroud)
当然,呼叫者仍然可以忽略值在out
PARAM,但你叫他们的注意.
这是一种罕见的需求; 更常见的情况是,您应该使用异常来处理真正的问题,或者返回具有"FYI"状态信息的对象,但是在某些情况下这很重要.
它主要是偏好
我更喜欢返回,如果你有多个返回,你可以将它们包装在Result DTO中
public class Result{
public Person Person {get;set;}
public int Sum {get;set;}
}
Run Code Online (Sandbox Code Playgroud)
您几乎应该总是使用返回值.' out
'参数会对许多API,组合等产生一些摩擦.
想到的最值得注意的异常是当你想要返回多个值时(.Net Framework在4.0之前没有元组),例如TryParse
模式.
您只能有一个返回值,而可以有多个out参数。
在这种情况下,您只需要考虑参数。
但是,如果您需要从方法中返回多个参数,则可能要查看从OO方法返回的内容,并考虑是否最好返回带有这些参数的对象或结构。因此,您又回到了返回值。