我正在创建一个函数,我需要传递一个对象,以便它可以被函数修改。有什么区别:

public void myFunction(ref MyClass someClass)

and

public void myFunction(out MyClass someClass)

我应该用哪个,为什么?


当前回答

对于那些以身作则的人(比如我),以下是安东尼·科索夫所说的。

我创建了一些ref、out和其他例子来说明这一点。我并没有介绍最佳实践,只是举例来理解它们之间的差异。

https://gist.github.com/2upmedia/6d98a57b68d849ee7091

其他回答

ref修饰符的意思是:

该值已经设置,并且 该方法可以读取和修改它。

out修饰符的意思是:

Value未被设置,并且在设置之前不能被方法读取。 方法必须在返回之前设置它。

ref和out就像c++中传递引用和传递指针一样。

对于ref,参数必须声明并初始化。

对于out,实参必须声明,但可以初始化,也可以不初始化

        double nbr = 6; // if not initialized we get error
        double dd = doit.square(ref nbr);

        double Half_nbr ; // fine as passed by out, but inside the calling  method you initialize it
        doit.math_routines(nbr, out Half_nbr);

“贝克”

这是因为第一个将字符串引用更改为指向“Baker”。更改引用是可能的,因为您通过ref关键字传递了它(=>是对字符串引用的引用)。 第二个调用获取字符串引用的副本。

弦一开始看起来很特别。但字符串只是一个引用类,如果你定义

string s = "Able";

那么s是一个包含文本“Able”的字符串类的引用! 对同一个变量via的另一个赋值

s = "Baker";

不改变原来的字符串,但只是创建一个新的实例,让我们指向该实例!

你可以试试下面的小代码示例:

string s = "Able";
string s2 = s;
s = "Baker";
Console.WriteLine(s2);

你想要什么? 您将得到的仍然是“Able”,因为您只是将s中的引用设置为另一个实例,而s2指向原始实例。

编辑: String也是不可变的,这意味着根本没有修改现有字符串实例的方法或属性(你可以尝试在文档中找到一个,但你找不到:-))。所有字符串操作方法都会返回一个新的字符串实例!(这就是为什么你在使用StringBuilder类时经常会得到更好的性能)

它们几乎是一样的——唯一的区别是,作为out形参传递的变量不需要初始化,使用ref形参的方法必须将其设置为某个值。

int x;    Foo(out x); // OK 
int y;    Foo(ref y); // Error

Ref形参用于可能被修改的数据,out形参用于已经使用返回值的函数(例如int.TryParse)的额外输出数据。

简洁的回答。

ref和out关键字都用于引用传递。 关键字为ref的变量必须有一个值或必须引用一个对象 或者在它传递之前为null。 与ref不同,关键字为out的变量必须有一个值或必须 在对象传递后引用对象或null以及不需要 在传递之前有一个值或引用一个对象。