1

也许是一个老问题,但在互联网上找不到任何全面的东西。

如果 C# 中默认的参数传递方法是By value,那么它如何影响初始 Reference Type 变量?

即在下面的示例中,如果它是按值传递的参数,为什么它会打印“Hello World”而不仅仅是“Hello”?

void Foo (StringBuilder x)
{
    x.Append (" World");
}   

StringBuilder y = new StringBuilder();
y.Append ("Hello");
Foo (y);
Console.WriteLine (y);
4

6 回答 6

4

首先,了解C#中有两种基本类型:值类型引用类型

此外,这些类型中的每一种都可以按值按引用传递给方法。(因此,这意味着实际上有四种方法可以将参数传递给方法。)

无论您如何传递引用类型(按值或按引用),您都可以更改该引用指向的值!

现在,关于您的特定示例,您的问题参数的类型StringBuilder是参考类型。(StringBuilder是一个,类是引用类型。)同样,因为您将引用类型传递给您的方法,您可以在该方法内更改与该引用关联的值。

最后,请注意您正在按值传递引用类型参数。相反,如果您要通过引用传递您的引用类型,然后将其设置为null,您实际上会破坏与引用关联的值。(这与将参数变量设置为方法null 外部相同。)

您可以在此处找到更全面、更易读的解释:C# 概念:值与引用类型

于 2013-12-12T16:48:15.460 回答
3

因为 StringBuilder 是一个mutable类,将通过引用传递。您使用 string 而不是 string builder 将是Hello因为 string 是immutable. int同样对于像, , ... 这样的值类型enum也没有任何变化。

为简单起见,值类型是结构、枚举、原始类型……而引用类型是类,但正如我提到的,有一些类(如字符串)是不可变的,实际上它们将按值传递。

于 2011-11-08T10:26:45.323 回答
3

该参数仍然是按值传递,但参数变量x具有StringBuilder对象的引用。

引用变量 y 具有 StringBuilder 对象的引用

StringBuilder y = new StringBuilder();

并且 StringBuilder 对象的引用被复制到 Foo 的参数 x 中。

Foo (y);
于 2011-11-08T10:29:10.080 回答
2

int默认情况下,除了原始类型(例如byte等)之外的任何内容都是通过引用传递的。您正在将相同的StringBuilder实例传递给该方法。

于 2011-11-08T10:27:05.057 回答
1

StringBuilder是一个类,所以会通过引用传递。

阅读更多:值与引用类型

于 2011-11-08T10:28:13.903 回答
1

比较以下。首先使用 StringBuilder(引用类型):

    public struct Tmd
    {
        public StringBuilder sb;
    }

    public void DoIt(Tmd a)
    {
        a.sb.Append(" World!");
    }

    public void Main()
    {
        Tmd a = new Tmd();
        a.sb = new StringBuilder();
        a.sb.Append("Hello");
        DoIt(a);
        Console.WriteLine(a.sb); // Hello World
    }

这里复制了结构,以及对 StringBuilder 的引用以及它,但不复制 StringBuilder 本身。

现在有了一个可变结构(值类型):

    public struct EvilMutable
    {
        public int i;
    }

    public struct Tmd
    {
        public EvilMutable em;
    }

    public void DoIt(Tmd a)
    {
        a.em.i += 1;
    }

    public void DoIt(EvilMutable em)
    {
        em.i += 1;
    }

    public void Main()
    {
        Tmd a = new Tmd();
        a.em.i += 5;
        Console.WriteLine(a.em.i); // 5
        DoIt(a);
        Console.WriteLine(a.em.i); // 5 (unchanged)
        DoIt(a.em);
        Console.WriteLine(a.em.i); // 5 (unchanged)
    }

在这种情况下,一切都复制了。但是,如果我们将其更改为引用类型:

    public class Tmd
    {
        public EvilMutable em;
    }

然后,我们会得到这个:

        Tmd a = new Tmd();
        a.em.i += 5;
        Console.WriteLine(a.em.i); // 5
        DoIt(a);
        Console.WriteLine(a.em.i); // 6
        DoIt(a.em);
        Console.WriteLine(a.em.i); // 6 (unchanged)
于 2012-10-02T15:40:28.463 回答