使用REF和OUT关键字在C#中按值传递和传递值

Goo*_*ber 8 c# ref out pass-by-reference

这是我到目前为止所理解的:

通过价值

按值传递意味着传递参数的副本.对该副本的更改不会更改原始副本.

通过参考

通过引用传递意味着传递对原始的引用.对引用的更改会影响原始引用.

REF关键字

REF告诉编译器在进入函数之前初始化对象.REF表示该值已经设置,因此该方法可以读取并修改它.REF有两种方式,包括进出.

OUT关键字

OUT告诉编译器该对象将在函数内初始化.OUT表示该值尚未设置,因此必须在调用return之前设置.OUT只是一种方式,即出局.

那么在什么情况下你会结合使用ref和out关键字,通过引用传递还是通过值传递?例子会有很大帮助.

非常感谢.

Hen*_*man 18

你会永远相结合ref,并out在1个参数.它们都意味着"通过引用传递".

您当然可以在一种方法中组合ref参数和输出参数.

之间的区别refout主要在于意图.ref信号2路数据传输,out表示1路.

但除了意图之外,C#编译器还会跟踪明确赋值,这会产生最显着的差异.它还可以防止误读(读取)out参数.

void SetOne(out int x) 
{
  int y = x + 1; // error, 'x' not definitely assigned.
  x = 1;         // mandatory to assign something
}

void AddTwo(ref int x)
{
    x = x + 2;  // OK, x  is known to be assigned
}

void Main()
{
    int foo, bar;

    SetOne(out foo); // OK, foo does not have to be assigned
    AddTwo(ref foo); // OK, foo assigned by SetOne
    AddTwo(ref bar); // error, bar is unassigned
}
Run Code Online (Sandbox Code Playgroud)


Eri*_*ert 8

非常感谢

通过正确和谨慎地使用语言,您的理解将得到改善.

按值传递意味着传递参数的副本.

是的,这完全准确.

对该副本的更改不会更改原始副本.

不完全是.首先要仔细区分值变量.考虑:

class Foo { public int x; }
...
void N() 
{
  Foo blah = new Foo();
  blah.x = 0;
  M(blah);
}
...
void M(Foo foo)
{
  foo.x = 123; // changes blah.x
  foo = null; // does not change blah
}
Run Code Online (Sandbox Code Playgroud)

这里的变量是x,blah和foo.x是一个字段,blah是本地的,foo是一个形式参数.

这里的值是null,0,123,以及对Foo实例的引用. 该参考是一个值.了解这一事实至关重要.

通过将变量blah的值复制到变量foo中来传递blah值的副本.blah的值是对Foo实例的引用.

M可以改变变量x的值,因为M有一个blah值的副本,它是对Foo的引用.当M将foo的内容更改为null时,这不会改变blah; foo包含blah值的副本.

通过引用传递意味着传递对原始的引用.

仔细选择你的措辞.什么是"原始"?

这将更好地说明为"通过引用传递意味着传递对参数的引用,该参数必须是变量".考虑它的一种更简单的方法是"通过引用传递使参数成为作为参数传递的变量的别名".

对引用的更改会影响原始引用.

由于参数和参数是彼此的别名,因此引用的更改不会影响原始参数; 参考文献是原文.它们都是相同的变量.

REF告诉编译器在进入函数之前初始化对象.

"对象"毫无意义.你的意思是"变量".

"ref"不"告诉编译器变量已初始化".相反,"ref"告诉编译器"你,编译器,必须验证变量是否已初始化".那是完全不同的!

REF表示已经设置了值,

不,ref要求已设置变量.没有"设定价值"这样的东西.

因此,该方法可以读取并修改它.

"它"的意思是"变量".

REF有两种方式,包括进出.

正确.

OUT告诉编译器该对象将在函数内初始化.

停止使用"对象"来表示"变量".如果你不再混淆完全不同的东西,你会更清楚地理解事情.变量不是对象.变量是存储位置,其中一些可能包含,其中一些值可能是对象的引用.

因此,out告诉编译器变量将在方法内初始化,是的,但这不太对.您忘记了方法将引发异常的情况,或者方法将进入无限循环 - 这些也是合法的方案.

OUT表示该值尚未设置,

同样,通过"值",您的意思是"变量".但这不准确.将初始化变量作为"out"参数传递是完全合法的.毫无意义,但合法.

因此必须在调用return之前设置.

没有叫"回归"; 方法被称为.但是,是的,该方法必须在正常返回之前为变量赋值.

OUT只是一种方式,即出局.

对.

那么在什么情况下你会结合使用ref和out关键字

没有这样的场景.