C# 返回值和输出参数哪个更好?
如果我们想从方法中获取一个值,我们可以使用返回值,如下所示:C# 返回值和输出参数哪个更好?,c#,reference,C#,Reference,如果我们想从方法中获取一个值,我们可以使用返回值,如下所示: public int GetValue(); Console.WriteLine(GetValue().ToString("g")); 或: 我真的不明白它们之间的区别,所以,不知道哪一个更好。你能给我解释一下吗 谢谢。我更喜欢以下内容,而不是这个简单示例中的任何一个 public int Value { get; private set; } 但是,它们都非常相似。通常,只有当需要从方法传回多个值时,才会使用
public int GetValue();
Console.WriteLine(GetValue().ToString("g"));
或:
我真的不明白它们之间的区别,所以,不知道哪一个更好。你能给我解释一下吗
谢谢。我更喜欢以下内容,而不是这个简单示例中的任何一个
public int Value
{
get;
private set;
}
但是,它们都非常相似。通常,只有当需要从方法传回多个值时,才会使用“out”。如果您想在方法中发送一个值,可以选择“ref”。我的方法是最好的,如果您只返回一个值,但如果您想传递一个参数并返回一个值,则可能会选择您的第一个选择。这是首选
我更喜欢返回,如果您有多个返回,您可以将它们包装在结果DTO中
public class Result{
public Person Person {get;set;}
public int Sum {get;set;}
}
什么更好,取决于你的特殊情况存在
out
的原因之一是为了方便从一个方法调用返回多个值:
public int ReturnMultiple(int input, out int output1, out int output2)
{
output1 = input + 1;
output2 = input + 2;
return input;
}
因此,从定义上讲,一个并不比另一个好。但通常你会想要使用一个简单的报税表,除非你有上述情况
编辑:
这是一个示例,演示了关键字存在的原因之一。以上内容决不是最佳实践。您几乎应该始终使用返回值。”<代码>输出'参数会对许多API、组合性等产生一些摩擦 想到的最值得注意的例外是,当您想要返回多个值时(.Net Framework直到4.0才有元组),例如使用
TryParse
模式。当方法没有任何其他可返回的内容时,返回值几乎总是正确的选择。(事实上,如果我可以选择的话,我想不出任何情况下我会想要一个带有out
参数的void方法。C#7的Deconstruct
语言支持的解构方法是这条规则非常非常罕见的例外。)
除此之外,它还可以阻止调用方单独声明变量:
int foo;
GetValue(out foo);
vs
Out值还可以防止像这样的方法链接:
public int GetValue();
Console.WriteLine(GetValue().ToString("g"));
(事实上,这也是属性设置器的问题之一,这也是构建器模式使用返回构建器的方法的原因,例如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): ");
}
}
结果:
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
差异出现在“post”步骤,即局部变量或参数更改后。在ReturnValue测试中,这对静态
值
变量没有影响。在输出参数测试中,值
变量通过tmp=10行改变代码>通常,您应该更喜欢返回值而不是out参数。如果您发现自己编写的代码需要做两件事,那么Out参数是一个必要的缺点。一个很好的例子是Try模式(比如Int32.TryParse)
让我们考虑一下你的两个方法的调用方需要做什么。对于第一个例子,我可以写这个
int foo = GetValue();
请注意,我可以在一行中声明一个变量并通过您的方法分配它。对于第二个例子,它看起来像这样
int foo;
GetValue(out foo);
我现在被迫提前声明变量,并在两行上编写代码
更新
当问这些类型的问题时,最好看一下.NET Framework设计指南。如果你有书的版本,那么你可以看到安德斯·赫兹伯格和其他人关于这个主题的注释(第184-185页),但是在线版本在这里
如果您发现自己需要从一个API返回两个东西,那么将它们包装在一个结构/类中比使用out参数要好。它们都有不同的用途,编译器不会对它们进行相同的处理。如果方法需要返回值,则必须使用return。Out用于方法需要返回多个值的地方
如果使用return,则数据首先写入方法堆栈,然后写入调用方法的堆栈。而在out的情况下,它直接写入调用方法堆栈。不确定是否还有任何差异。您只能有一个返回值,而可以有多个输出参数
你只需要考虑这些情况下的参数。
但是,如果需要从方法返回一个以上的参数,您可能希望查看从OO方法返回的内容,并考虑如果返回具有这些参数的对象或结构是否更好。因此,您又回到了返回值。
没有真正的区别。Out参数在C#中,以允许方法返回多个值,仅此而已
然而,有一些细微的差异,但其中没有一个是真正重要的:
使用out参数将强制您使用以下两行:
int n;
GetValue(n);
使用返回值时,您可以在一行中完成此操作:
int n = GetValue();
另一个区别(仅适用于值类型,并且仅适用于C#不内联函数的情况)是,当函数返回时,使用return value必然会生成值的副本,而使用OUT参数则不一定如此。正如其他人所说:return value,
Method1(); // Return values can be discard quite easily, even accidentally
int resultCode;
Method2(out resultCode); // Out params are a little harder to ignore
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;
}
var result = DoThing();
if (result.Success)
{
result = DoOtherThing()
if (result.Success)
{
result = DoFinalThing()
if (result.Success)
{
success = true;
}
}
}
var result;
if (DoThing(out result))
{
if (DoOtherThing(out result))
{
if (DoFinalThing(out result))
{
success = true;
}
}
}