您能告诉我 out
参数的确切用法吗?
答案 0 :(得分:17)
良好使用out
参数的最佳示例是TryParse
方法。
int result =-1;
if (!Int32.TryParse(SomeString, out result){
// log bad input
}
return result;
使用TryParse
代替ParseInt
消除了处理异常的需要,并使代码更加优雅。
out
参数基本上允许方法返回多个值。
答案 1 :(得分:6)
a上的out方法参数关键字 method参数导致方法 引用相同的变量 传递给方法。任何变化 对方法中的参数进行了处理 将反映在该变量中 当控制权回传给 呼叫方法。
声明out方法非常有用 你想要一个方法来返回多个 值。一种使用out的方法 参数仍然可以返回一个值。一个 方法可以有多个出来 参数。
使用out参数,参数 必须明确传递给 方法作为一个out参数。价值 out参数不会被传递 到out参数。
作为out参数传递的变量 无需初始化。然而 out参数必须赋值 在方法返回之前。
示例:
using System;
public class MyClass
{
public static int TestOut(out char i)
{
i = 'b';
return -1;
}
public static void Main()
{
char i; // variable need not be initialized
Console.WriteLine(TestOut(out i));
Console.WriteLine(i);
}
}
答案 2 :(得分:3)
http://msdn.microsoft.com/en-us/vcsharp/aa336814.aspx
Out参数只输出参数,这意味着它们只能从函数中传回一个值。我们通过在参数数据类型前加上out修饰符来创建一个“out”参数。当传递“out”参数时,只将未分配的引用传递给函数。
using System;
class ParameterTest
{
static void Mymethod(out int Param1)
{
Param1=100;
}
static void Main()
{
int Myvalue=5;
MyMethod(Myvalue);
Console.WriteLine(out Myvalue);
}
}
由于“out”参数的值被传递回调用部分,因此上述程序的输出将为100。注意
修饰符“out”应该在即使在调用部分中传递的参数之前。在为函数赋值之前,不能在函数内使用“out”参数。在方法返回之前,应将值赋给“out”参数。
答案 3 :(得分:2)
来自http://msdn.microsoft.com/en-us/vcsharp/aa336814.aspx
考虑输出参数的一种方法是它们就像方法的附加返回值。当方法返回多个值时,它们非常方便,在本例中为firstName和lastName。但是,可以滥用输出参数。如果你发现自己编写了一个包含许多参数的方法,那么你应该考虑重构代码。一种可能的解决方案是将所有返回值打包到单个结构中。
相比之下,ref参数被认为是被调用者最初分配的。因此,被调用者在使用之前不需要分配给ref参数。参数传入和传出方法。
答案 4 :(得分:2)
除了允许多个返回值之外,另一个用途是在将大值类型复制到方法时减少开销。当您将某些内容传递给某个方法时,会生成该内容的值的副本。如果它是引用类型(例如字符串),则会生成引用的副本(引用类型的值)。但是,当您复制值类型(struct
,如int
或double
)时,会复制整个事物的副本(值类型的值是事物本身)。现在,引用是4个字节(在32位应用程序上),int
是4个字节,因此复制不是问题。但是,可能有非常大的值类型,虽然不推荐,但有时可能需要它。当你有一个64字节的值类型时,将它复制到方法的成本是高昂的(特别是当你出于性能原因使用如此大的struct
时)。当您使用out
时,没有对象的副本,您只需引用相同的内容。
public struct BigStruct
{
public int A, B, C, D, E, F, G, H, J, J, K, L, M, N, O, P;
}
SomeMethod(instanceOfBigStruct); // A copy is made of this 64-byte struct.
SomeOtherMethod(out instanceOfBigStruct); // No copy is made
直接与此相符的第二个用法是,因为你没有复制结构,而是像在方法之外那样引用方法中的相同的事物,对方法内部对象所做的任何更改都将保留在方法外部。在引用类型中已经是这种情况,但在值类型中却不是这样。
一些例子:
public void ReferenceExample(SomeReferenceType s)
{
s.SomeProperty = "a string"; // The change is persisted to outside of the method
}
public void ValueTypeExample(BigStruct b)
{
b.A = 5; // Has no effect on the original BigStruct that you passed into the method, because b is a copy!
}
public void ValueTypeExampleOut(out BigStruct b)
{
b = new BigStruct();
b.A = 5; // Works, because you refer to the same thing here
}
现在,您可能已经注意到ValueTypeExampleOut
内部new
实例BigStruct
。这是因为,如果您使用out
,则必须在退出方法之前将变量分配给某个内容。
然而,另一个关键字ref
是相同的,除了您不必在方法中分配它。但是,这也意味着你不能传入一个未赋值的变量,这会使得那个很好的Try ..模式在与ref
一起使用时无法编译。
int a;
if(TrySomething(out a)) {}
这是有效的,因为TrySomething
被迫向a
分配内容。
int a;
if(TrySomething(ref a)) {}
这不起作用,因为a
未分配(刚刚声明)而ref
要求您仅将其与指定的变量一起使用。
这可行,因为已分配a
:
int a = 0;
if(TrySomething(ref a)) {}
但是,在这两种情况下(ref
和out
),a
方法中对TrySomething
所做的任何更改都会保留到a
。
正如我已经说过的,对引用类型所做的更改将保留在您创建它们的方法之外,因为通过引用,您可以引用相同的内容。
然而,这没有做任何事情:
public void Example(SomeReferenceType s)
{
s = null;
}
在这里,您只需将s
的引用的副本设置为null,这仅存在于方法的范围内。它对传入方法的任何内容都没有影响。
如果您想这样做,无论出于何种原因,请使用:
public void Example1(ref SomeReferenceType s)
{
s = null; // Sets whatever you passed into the method to null
}
我认为这涵盖了out
和ref
的所有用例。
答案 5 :(得分:1)
典型的用例是一个需要返回多个东西的方法,因此它不能只使用返回值。通常,返回值用于成功标志,而 out 参数在方法成功时设置值。
经典的例子是:
public bool TryGet(
string key,
out string value
)
如果返回true,则设置value。否则,事实并非如此。这使您可以编写如下代码:
string value;
if (!lookupDictionary.TryGet("some key", out value))
value = "default";
请注意,这不需要您在使用索引器之前调用Contains,这使得它更快更干净。我还要补充一点,与非常相似的 ref 修饰符不同,如果 out 参数从未初始化,编译器不会抱怨。
答案 6 :(得分:1)
简而言之,通过引用将任何变量传递给函数,以便当函数从执行返回时对该函数进行的对该变量的任何更改将保持不变。
答案 7 :(得分:0)
Jon Skeet在this文章中详细介绍了传递参数的不同方法。简而言之,out参数是未初始化传递给方法的参数。然后需要该方法在任何可能的返回之前初始化参数。
答案 8 :(得分:0)
一般来说,如果我们没有获得返回值,我们就无法获取函数内部的变量。 但是使用关键字“out”我们可以通过函数更改它的值。