在 C# 中使用“ref”关键字 [重复]

Posted

技术标签:

【中文标题】在 C# 中使用“ref”关键字 [重复]【英文标题】:Use of 'ref' keyword in C# [duplicate] 【发布时间】:2011-06-16 07:17:07 【问题描述】:

可能的重复:Why use ref keyword when passing an Object?When to pass ref keyword in

C# 中“ref”关键字的正确用法是什么。我相信已经有很多关于此的讨论线程,但我不清楚的是:

    如果要传入引用对象,是否需要 ref 关键字?我的意思是当你在堆中创建一个对象时,它并不总是通过引用传递。这是否必须明确标记为参考?

【问题讨论】:

大量重复...Why use ref keyword when passing an Object?、C# ref keyword usage、When to pass ref keyword in、When is using the C# ref keyword ever a good idea? 等。所有这些似乎都回答了您的问题。有没有他们没有解决的数字 2? 还必须阅读我们自己的 Jon Skeet 关于该主题的文章:Parameter passing in C#。不幸的是,我不能投票关闭作为该副本的副本。 ;-) 【参考方案1】:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace InOutRef

    static class InOutRef
    
        public static void In(int i)
        
            Console.WriteLine(i);
            i=100;
            Console.WriteLine(i);
        
        public static void Ref(ref int i)
        
            Console.WriteLine(i);
            i=200;
            Console.WriteLine(i);
        
        public static void Out(out int i)
        
            //Console.WriteLine(i); //Error Unsigned Ref
            i=300;
            Console.WriteLine(i);
        
    

    class Program
    
        static void Main(string[] args)
        
            int i = 1;
            InOutRef.In(i); //passed by value (in only)
            Debug.Assert(i==1);
            InOutRef.Ref(ref i); //passed by ref (in or out)
            Debug.Assert(i == 200);
            InOutRef.Out(out i); //passed by as out ref (out only)
            Debug.Assert(i == 300);
        
    

我的回答不能再直白了。当使用 in 时,代码将不会记住引用更改,例如经典的 Java 交换 question。但是,当使用 ref 时,它将类似于 VB.NET,因为它会记住 inout 的变化。如果您使用 out 参数,则意味着必须在返回之前声明它(这是由编译器强制执行的)。

输出: 1 //1 来自主 100 //100 来自 in 1 //1 不会从 In 中记住 200 //200 来自参考 //此处应为 200,但 out 强制输出参数(未打印,因为已注释掉) 300 //300 只出 按任意键继续 。 . .

【讨论】:

【参考方案2】:

这里的答案中有很多令人困惑的错误信息。理解这一点的最简单方法是放弃“ref”意味着“通过引用”的想法。更好的思考方式是“ref”的意思是“我希望被调用方的这个形式参数成为调用方特定变量的别名”。

当你说

void M(ref int y)  y = 123; 
...
int x = 456;
M(ref x);

也就是说“在调用 M 期间,被调用方的形参 y 是调用方变量 x 的另一个名称”。将 123 分配给 y 与将 123 分配给 x 完全相同,因为它们是同一个变量,一个有两个名称的变量。

就是这样。不要考虑引用类型或值类型或其他任何东西,不要考虑按引用传递或按值传递。所有“ref”的意思是“暂时为这个变量命名”。

【讨论】:

【参考方案3】:

使用ref 表示将引用 传递给函数。

默认行为是函数接收对同一对象的新引用。这意味着如果您更改引用的值(例如,将其设置为新对象),那么您将不再指向原始的源对象。当您使用 ref 传递时,更改引用的值会更改源引用 - 因为它们是相同的。

考虑一下:

public class Thing

    public string Property get;set;


public static void Go(Thing thing)

    thing = new Thing();
    thing.Property = "Changed";


public static void Go(ref Thing thing)

    thing = new Thing();
    thing.Property = "Changed";

然后如果你运行

var g = new Thing();

// this will not alter g
Go(g);

// this *will* alter g
Go(ref g);

【讨论】:

+1 最后,一个正确的答案。把这样的问题留得太久是很危险的,因为那里有太多的错误信息。很高兴在这里使用除反对票以外的其他东西。 害怕有人反对这个;我不想和那个人一起工作! 可能有人对这里给出的答案的大量反对票感到不安。这是我没有尝试提供自己的主要原因。更糟糕的是想象与仍然在 cmets 中尝试和争论的人一起工作。【参考方案4】:

我相信 ref 关键字表明您通过引用而不是值传递对象。例如:

void myfunction(ref object a) 
a = new Something();

会改变调用函数中a的值 不过,

void myfunction(object a) 
a = new Something();

将在本地更改 a 的值,但不会在调用函数中更改。您仍然可以更改项目的属性,但不能设置项目本身的值。例如; a.someproperty = value;

在这两种情况下都可以使用。

【讨论】:

第二个例子(没有 ref)将无法编译,因为这就像说 1 = 3。1 不可能等于 3。但是,使用 ref。好像在说。 x = 1。然后 x = 3。 第二个例子会“工作”,但可能会产生意想不到的结果! 我猜它编译,但它不会改变调用函数上下文中 a 的值。 在对a 的引用在本地成功重新分配的意义上是可行的。但这种变化不会反映回调用函数。它肯定不会导致编译时错误。

以上是关于在 C# 中使用“ref”关键字 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

“ref”关键字和引用类型[重复]

C#使用引用参数[重复]

C#中关键字ref和out的区别

C# ref与out关键字区别

C#:关键字out和ref之间的区别

c# out ref