为什么在C#中引用和退出?

时间:2009-08-22 22:04:54

标签: c#

使用关键字 ref 时,调用代码需要初始化传递的参数,但使用关键字 out ,我们不需要这样做。

  • 为什么我们不在任何地方使用 out
  • 两者之间有什么区别?
  • 请举例说明我们需要使用 ref 并且无法使用 out

7 个答案:

答案 0 :(得分:16)

答案在MSDN article中给出。从那篇文章:

  

两个参数传递模式   由outref处理的是巧妙的   不同,但他们都非常   共同。微妙的区别   这些模式导致一些非常普遍   编程错误。其中包括:

     
      
  1. 没有为out分配值   所有控制流路径中的参数
  2.   
  3. 不为变量赋值   用作ref参数
  4.         

    因为C#语言分配   不同的明确分配规则   这些不同的参数传递   模式,这些常见的编码错误   被编译器捕获为   不正确的C#代码。

         

    决定包括的关键   refout参数传递   模式是允许编译器   检测这些常见的编码错误   值得额外的复杂性   同时拥有refout参数   用语言传递模式。

答案 1 :(得分:14)

outref的一种特殊形式,其中引用的内存不应在调用之前初始化。

在这种情况下,C#编译器强制在方法返回之前分配out变量,并且在分配变量之前不使用该变量。

out无效但ref无效的两个示例:

void NoOp(out int value) // value must be assigned before method returns
{
}

void Increment(out int value) // value cannot be used before it has been assigned
{
    value = value + 1;
}

答案 2 :(得分:8)

这些答案都没有让我满意,所以这是我对refout的看法。

我的回答是以下两页的摘要:

  1. ref (C# Reference)
  2. out (C# Reference)

  3. <强>比较

    1. 方法定义和调用方法都必须明确使用ref / out关键字
    2. 两个关键字都会导致参数通过引用传递(偶数值类型
    3. 但是,当通过引用
    4. 传递值类型时,没有boxing
    5. 无法通过outref传递属性,因为属性确实是方法
    6. ref / out在编译时不被视为方法签名的一部分,因此如果方法之间的唯一区别是方法之一采用{{1},则方法不能重载参数和另一个采用ref参数
    7. <强>对比度

      out

      1. 必须在传递之前进行初始化
      2. 可用于将值传递给方法
      3. ref

        1. 在传递之前不必初始化
        2. 在方法返回
        3. 之前,需要调用方法来指定值
        4. 不能用于将值传递给方法

        5. <强>实施例

          无法编译,因为只有方法签名的差异为out / ref

          out

          使用public void Add(out int i) { } public void Add(ref int i) { } 关键字:

          ref

          使用public void PrintNames(List<string> names) { int index = 0; // initialize first (#1) foreach(string name in names) { IncrementIndex(ref index); Console.WriteLine(index.ToString() + ". " + name); } } public void IncrementIndex(ref int index) { index++; // initial value was passed in (#2) } 关键字:

          out

          作者随机备注

          1. 在我看来,使用public void PrintNames(List<string> names) { foreach(string name in names) { int index; // not initialized (#1) GetIndex(out index); Console.WriteLine(index.ToString() + ". " + name); } } public void GetIndex(out int index) { index = IndexHelper.GetLatestIndex(); // needs to be assigned a value (#2 & #3) } 关键字的概念类似于使用out枚举值ParameterDirection在ADO.NET中声明输出参数
          2. C#中的数组是通过引用传递的,但是为了重新分配数组引用以影响调用代码中的引用,必须使用Output关键字
          3. 示例:

            ref

            有关参考类型与价值类型的详情,请参阅Passing Reference-Type Parameters (C# Programming Guide)

答案 3 :(得分:1)

当你需要使用ref而不是out时,一个人为的例子如下:

public void SquareThisNumber(ref int number) 
{
   number = number * number;
}

int number = 4;
SquareThisNumber(ref number);

我们希望number成为输入输出变量,因此我们使用ref。如果我们使用了out,那么编译器会在使用之前初始化out参数时给出错误。

答案 4 :(得分:1)

ref关键字允许您更改参数的值。被调用的方法可以是调用链中的中间链接。使用out关键字的方法只能在调用链的开头使用。

另一个优点是现有值可以在方法的逻辑中使用,并且仍然保持返回值。

在Oracle函数中有显式的IN(默认值以及未设置方向时获得的内容)IN / OUT和OUT参数。等效是正常的(只是参数),ref [参数]和out [参数]。

答案 5 :(得分:0)

编译器知道在调用之前不应设置out变量。这允许它们在使用前声明。但是它知道它必须在返回时使用的函数之前设置。

答案 6 :(得分:0)

当我们在调用前缀为out关键字的方法时传递值时,它会将它视为完全不同,就像我们没有将它传递给方法一样。相反,我们实际上是从out方法的定义部分收集(outing)out变量的值到我们调用该方法的method out变量参数。

所以out variable是在方法定义中完成的处理的输出,这就是我们需要创建它,初始化它并仅在定义中修改它的原因。

当我们需要从特定方法返回多个值时,使用out变量。

ref变量的情况下,我们需要首先初始化它,因为它的内存位置被转换为方法定义作为参数。想想如果我们在传递之前没有初始化它会发生什么?