out 参数修饰符(C# 参考)out parameter modifier (C# Reference)

out 关键字通过引用传递参数。The out keyword causes arguments to be passed by reference. 它让形参成为实参的别名,这必须是变量。It makes the formal parameter an alias for the argument, which must be a variable. 换而言之,对形参执行的任何操作都是对实参执行的。In other words, any operation on the parameter is made on the argument. 它与 ref 关键字相似,只不过 ref 要求在传递之前初始化变量。It is like the ref keyword, except that ref requires that the variable be initialized before it is passed. 它也类似于 in 关键字,只不过 in 不允许通过调用方法来修改参数值。It is also like the in keyword, except that in does not allow the called method to modify the argument value. 若要使用 out 参数,方法定义和调用方法均必须显式使用 out 关键字。To use an out parameter, both the method definition and the calling method must explicitly use the out keyword. 例如:For example:

int initializeInMethod;
OutArgExample(out initializeInMethod);
Console.WriteLine(initializeInMethod);     // value is now 44

void OutArgExample(out int number)
{
    number = 44;
}

备注

out 关键字也可与泛型类型参数结合使用,以指定该类型参数是协变参数。The out keyword can also be used with a generic type parameter to specify that the type parameter is covariant. 有关在此上下文中使用 out 关键字的详细信息,请参阅 out(泛型修饰符)For more information on the use of the out keyword in this context, see out (Generic Modifier).

作为 out 参数传递的变量在方法调用中传递之前不必进行初始化。Variables passed as out arguments do not have to be initialized before being passed in a method call. 但是,被调用的方法需要在返回之前赋一个值。However, the called method is required to assign a value before the method returns.

inrefout 关键字不被视为用于重载决议的方法签名的一部分。The in, ref, and out keywords are not considered part of the method signature for the purpose of overload resolution. 因此,如果唯一的不同是一个方法采用 refin 参数,而另一个方法采用 out 参数,则无法重载这两个方法。Therefore, methods cannot be overloaded if the only difference is that one method takes a ref or in argument and the other takes an out argument. 例如,以下代码将不会编译:The following code, for example, will not compile:

class CS0663_Example
{
    // Compiler error CS0663: "Cannot define overloaded 
    // methods that differ only on ref and out".
    public void SampleMethod(out int i) { }
    public void SampleMethod(ref int i) { }
}

但是,如果一个方法采用 refinout 参数,而另一个方法采用其他参数,则可以完成重载,如:Overloading is legal, however, if one method takes a ref, in, or out argument and the other has none of those modifiers, like this:

class OutOverloadExample
{
    public void SampleMethod(int i) { }
    public void SampleMethod(out int i) => i = 5;
}

编译器通过将调用站点上的参数修饰符与方法调用中使用的参数修饰符进行匹配,从而选择最佳重载。The compiler chooses the best overload by matching the parameter modifiers at the call site to the parameter modifiers used in the method call.

属性不是变量,因此不能作为 out 参数传递。Properties are not variables and therefore cannot be passed as out parameters.

不能将 inrefout 关键字用于以下几种方法:You can't use the in, ref, and out keywords for the following kinds of methods:

  • 异步方法,通过使用 async 修饰符定义。Async methods, which you define by using the async modifier.

  • 迭代器方法,包括 yield returnyield break 语句。Iterator methods, which include a yield return or yield break statement.

声明 out 参数Declaring out parameters

使用 out 参数声明方法是返回多个值的经典解决方法。Declaring a method with out arguments is a classic workaround to return multiple values. 自 C# 7.0 起,建议在类似方案中使用元组Beginning with C# 7.0, consider tuples for similar scenarios. 下面的示例使用 out 返回具有单个方法调用的三个变量。The following example uses out to return three variables with a single method call. 注意,第三个参数赋 null 值。Note that the third argument is assigned to null. 这使得方法可以有选择地返回值。This enables methods to return values optionally.

void Method(out int answer, out string message, out string stillNull)
{
    answer = 44;
    message = "I've been returned";
    stillNull = null;
}

int argNumber;
string argMessage, argDefault;
Method(out argNumber, out argMessage, out argDefault);
Console.WriteLine(argNumber);
Console.WriteLine(argMessage);
Console.WriteLine(argDefault == null);

// The example displays the following output:
//      44
//      I've been returned
//      True

调用具有 out 参数的方法Calling a method with an out argument

在 C# 6 及更早版本中,必须先在单独的语句中声明变量,然后才能将其作为 out 参数传递。In C# 6 and earlier, you must declare a variable in a separate statement before you pass it as an out argument. 下面的示例先声明了变量 number,然后再将它传递给将字符串转换为数字的 Int32.TryParse 方法。The following example declares a variable named number before it is passed to the Int32.TryParse method, which attempts to convert a string to a number.

string numberAsString = "1640";

int number;
if (Int32.TryParse(numberAsString, out number))
    Console.WriteLine($"Converted '{numberAsString}' to {number}");
else
    Console.WriteLine($"Unable to convert '{numberAsString}'");
// The example displays the following output:
//       Converted '1640' to 1640

从 C# 7.0 开始,可以在方法调用的参数列表而不是单独的变量声明中声明 out 变量。Starting with C# 7.0, you can declare the out variable in the argument list of the method call, rather than in a separate variable declaration. 这使得代码更简洁可读,还能防止在方法调用之前无意中向该变量赋值。This produces more compact, readable code, and also prevents you from inadvertently assigning a value to the variable before the method call. 下面的示例与上一个示例基本相同,不同之处在于它在对 Int32.TryParse 方法的调用中定义了 number 变量。The following example is like the previous example, except that it defines the number variable in the call to the Int32.TryParse method.

string numberAsString = "1640";

if (Int32.TryParse(numberAsString, out int number))
    Console.WriteLine($"Converted '{numberAsString}' to {number}");
else
    Console.WriteLine($"Unable to convert '{numberAsString}'");
// The example displays the following output:
//       Converted '1640' to 1640

在上一个示例中,number 变量被强类型化为 intIn the previous example, the number variable is strongly typed as an int. 你也可以声明一个隐式类型本地变量,如以下示例所示。You can also declare an implicitly typed local variable, as the following example does.

string numberAsString = "1640";

if (Int32.TryParse(numberAsString, out var number))
    Console.WriteLine($"Converted '{numberAsString}' to {number}");
else
    Console.WriteLine($"Unable to convert '{numberAsString}'");
// The example displays the following output:
//       Converted '1640' to 1640

C# 语言规范C# Language Specification

有关详细信息,请参阅 C# 语言规范For more information, see the C# Language Specification. 该语言规范是 C# 语法和用法的权威资料。The language specification is the definitive source for C# syntax and usage.

请参阅See also