何时传递ref关键字

duk*_*uka 9 c#

我已经阅读了passng和不在参数中传递ref之间的区别,但是,我何时想要使用它们?

例如,我在一个方法中有一些逻辑可以重构为它自己的方法.Resharper 4.5将参数之一作为ref类型,但如果我手动进行重构,我认为我不会这样做.

显然我缺少一些理解.也许当编码中的某些类型或某些场景错过ref关键字时会发生什么情况会有所帮助?

谢谢

Eri*_*ert 8

让我把它分解为两个问题:

1)何时应该在编写方法时使用ref/out形式参数声明?

当您希望您的方法能够读取和写入从调用者传入的变量时,请使用ref/out ,而不是仅仅读取值.

2)为什么"提取方法"重构会产生ref参数?

我不知道Resharper的细节,但我可以猜一猜.考虑以下邪恶的可变值类型:

struct S 
{ 
  private int x;
  public int X() { return this.x; } 
  public void M() { this.x += 1; } 
}
Run Code Online (Sandbox Code Playgroud)

你有一个方法:

void Foo() 
{
    S s = new S();
    Fred(s);
    Blah(s);
    Bar(s);
    s.M();
    Console.WriteLine(s.X()); // prints 1
}
Run Code Online (Sandbox Code Playgroud)

你在中间位上做"提取方法":

void NewMethod(ref S s)
{
    Blah(s);
    Bar(s);
    s.M();
}

void Foo() 
{
    S s = new S();
    Fred(s);
    NewMethod(ref s);
    Console.WriteLine(s.X()); // still prints 1
}
Run Code Online (Sandbox Code Playgroud)

相反,如果您创建了一个没有"ref"的方法,那么调用NewMethod会将s的副本传递给NewMethod.请记住,值类型按值复制; 这就是为什么我们称它们为"价值类型".它将是变异的副本,然后sX()返回零.重构在程序中引入语义变化是一个坏主意,重构引擎很难知道给定方法是否依赖于值类型的可变性.

这只是你应该避免使用可变值类型的另一个原因.