【问题标题】:Passing variable by Ref. or Value Dilemma通过 Ref 传递变量。或价值困境
【发布时间】:2011-11-15 22:19:24
【问题描述】:

我有一些静态的 void 方法。

通过引用或值传递变量更好吗,因为我将大量文本传递给这些变量:

public static void renderText(ref StringBuilder build)
{
  //Do your job.
}

那么有人可以解释一下,当我发送StringBuilder 的引用时会发生什么,它是否只访问这个StringBuilder? (它没有正确复制它!)。

以防万一我没有将输入参数的值或任何其他属性更改为方法。

那么,在这种情况下,变量足够大并且没有被操纵,我是否应该总是发送它的引用,如果是的话,它会干扰什么吗?

【问题讨论】:

标签: c# methods input-parameters


【解决方案1】:

非值类型总是通过引用传递。 ref 关键字的目的是让您将引用更改为方法内的对象。

您完全误解了传递的参数。阅读this article

【讨论】:

  • 不过,在通过 ref 传递引用类型时还是有区别的。
  • @Artem 我知道,不是开玩笑,但我认为我可以为此目的使用 pas by ref。这会很棘手
  • 否,引用类型参数默认仍按值传递。值是参考,仅此而已。称其为“通过引用传递”会使水域变得混乱。见pobox.com/~skeet/csharp/parameters.html
  • 谢谢乔恩,从现在开始我将使用“参考价值”:)
  • @Jon,旧讨论,但(功能上)引用类型的实例是通过引用传递的。它只是按值传递的引用。有趣的是,我们仍然没有很好的词汇来表达这一点。
【解决方案2】:

只要您处理引用类型(类,StringBuilderString 是),通过引用传递它们几乎没有意义,因为无论如何都不会复制。

【讨论】:

    【解决方案3】:

    请查看 Jon Skeet 的以下文章,其中他彻底解释了按引用传递或按值传递之间的区别。

    Parameter passing in C#

    或这篇说明前一篇文章的博文:

    http://rapidapplicationdevelopment.blogspot.com/2007/01/parameter-passing-in-c.html

    上一篇文章在其示例中实际上使用了 StringBuilder 类型,因此您可以清楚地看到您的案例中发生了什么。如果你通过引用传入 StringBuilder 类型,你会得到:

    通过引用传递的引用类型:

    【讨论】:

      【解决方案4】:

      按值传递参数

      默认情况下,C# 中的参数是按值传递的。这意味着在传递给方法时会创建一个值的副本:

      class Test
      {
          static void Foo(int p)
          {
              p = p + 1;             // Increment p by one.
              Console.WriteLine(p);  // Write p to screen.
          } 
      
          static void Main()
          {
              int x = 8;            
              Foo(x);               // Make a copy of x.
              Console.WriteLine(x); // x will still be 8.
          }
      }
      

      为 p 赋值不会改变变量 x 的内容,因为 p 和 x 位于不同的内存位置。

      按值传递引用元组参数会复制引用,但不会复制对象。字符串生成器的示例;这里 Foo 看到与 main 实例化的相同的 StringBuilder 对象,但对它有一个独立的 reference。所以 StrBuild 和 fooStrBuild 是引用相同 StringBuilder 对象的独立变量:

      class Test
      {
          static void Foo(StringBuilder fooStrBuild)
          {
              fooStrBuild.Append("testing");            
              fooStrBuild = null;
          } 
      
          static void Main()
          {
              StringBuilder StrBuild = new StringBuilder();
              Foo(strBuild);
              Console.WriteLine(StrBuild.ToString()); // "testing"
          }
      }
      

      因为 fooStrBuild 是引用的副本,所以更改其值不会更改 StrBuild。

      通过引用传递

      在下文中,p 和 x 指的是相同的内存位置:

      class Test
      {
          static void Foo(ref int p)
          {
              p = p + 1;             // Increment p by one.
              Console.WriteLine(p);  // Write p to screen.
          } 
      
          static void Main()
          {
              int x = 8;            
              Foo(ref x);           // Make a copy of x.
              Console.WriteLine(x); // x is now 9.
          }
      }
      

      因此 p 的值发生了变化。

      希望这会有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-24
        • 2015-03-13
        • 2011-06-15
        • 2020-03-05
        • 1970-01-01
        • 2020-12-20
        相关资源
        最近更新 更多