C#直接传递引用类型vs out参数

Dav*_*iov 9 c#

我有两种方法:

public void A(List<int> nums) 
{
    nums.Add(10);
}

public void B(out List<int> nums)
{
    nums.Add(10);
}
Run Code Online (Sandbox Code Playgroud)

这两个电话有什么区别?

List<int> numsA = new List<int>();
A(numsA);

List<int> numsB = new List<int>();
B(out numsB); 
Run Code Online (Sandbox Code Playgroud)

一般来说,我试图理解传递引用类型as-is或out参数之间的区别.

Tho*_*que 7

在您的示例中,方法B将无法编译,因为out参数被认为是未初始化的,因此您必须先初始化它,然后才能使用它.此外,在使用out参数调用方法时,您需要out在调用站点指定关键字:

B(out numsB);
Run Code Online (Sandbox Code Playgroud)

并且您不需要numbsB在调用之前初始化变量,因为它将被方法覆盖.

Jon Skeet有一篇很棒的文章解释了传递参数的各种方法:C#中的参数传递


pho*_*oog 5

A non-ref, non-out parameter, like a local variable, denotes a storage location. If the storage location's type is a reference type, then the storage location holds a reference to an instance of that type.

Ref and out parameters, by contrast, hold a reference to a storage location. That storage location could be a local variable, a field, or an array element. In other words, ref and out parameters introduce another layer of indirection. If you have a reference-type ref or out parameter in a method, it therefore represents a reference to a reference to an object.

Why would you want a reference to a reference to an object? In case you need to modify the reference to the object (as opposed to modifying the object itself).

This is a useful technique in some narrow circumstances. For example, you might want to write a function that orders two queues depending on which has the smaller value on top:

void OrderQueues(ref Queue<int> a, ref Queue<int> b)
{
    if (a.Peek <= b.Peek) return;
    var temp = a;
    a = b;
    b = temp;
}
Run Code Online (Sandbox Code Playgroud)

Out parameters are useful if you want to return more than one value from a method:

void OldestAndYoungest(IEnumerable<Person> people, out Person youngest, out Person oldest)
{
    youngest = null;
    oldest = null;
    foreach (var person in people)
    {
        if (youngest == null || person.Age < youngest.Age)
            youngest = person;
        if (oldest == null || oldest.Age < person.Age)
            oldest = person;
    }
}
Run Code Online (Sandbox Code Playgroud)

In my experience, ref and out parameters are fairly rare, and even rarer with reference types.

Note that a ref parameter must be initialized by the caller, while an out parameter must be initialized by the callee. If you never assign a value to the ref parameter, then it should probably be a "normal" parameter. If you never assign a value to an out parameter, as in your example, your code will not compile.


Roy*_*mir 0

out 关键字导致参数通过引用传递。这与 ref 关键字类似,只不过 ref 要求变量在传递之前进行初始化。要使用 out 参数,方法定义和调用方法都必须显式使用 out 关键字。例如:

https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/out-parameter-modifier