在C#中使用'ref'关键字

时间:2011-01-27 04:00:45

标签: c# .net

  

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

C#中'ref'关键字的正确用法是什么?我相信这方面有很多讨论主题,但我不清楚的是:

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

4 个答案:

答案 0 :(得分:22)

使用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 :(得分:15)

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

当你说

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

这就是说“在调用M时,被叫方的形式参数y是调用者侧变量x的另一个名称”。将123分配给y与将123分配给x完全相同,因为它们是相同的变量,一个具有两个名称的变量。

这就是全部。不要考虑引用类型或值类型或其他,不考虑通过引用传递或通过值传递。所有“ref”意味着“暂时为此变量创建第二个名称”。

答案 2 :(得分:0)

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

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

会改变调用函数中a的值 但是,

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

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

可以在两种情况下都有效。

答案 3 :(得分:0)

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);
        }
    }
}

我的回答不能再是字面意义了。在中使用时,代码将不会记住参考通道,例如经典Java交换question。但是,当使用 ref 时,它将类似于VB.NET,因为它会记住中的 out 中的更改。如果使用 out 参数,则表示必须在返回之前声明它(这由编译器强制执行)。

Output:
1                                  //1 from main 
100                                //100 from in
1                                  //1 is NOT remembered from In
200                                //200 from ref
//should be 200 here but out enforces out param (not printed because commented out)
300                                //300 is out only
Press any key to continue . . .