在C#中传递的默认参数

时间:2011-11-08 10:25:14

标签: c#

也许是一个老问题,但我没有在互联网上找到任何全面的内容。

如果C#中的默认参数传递方法是By值(根据this),那么它如何影响初始的Reference Type变量。

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

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

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

6 个答案:

答案 0 :(得分:3)

因为StringBuilder是mutable类,将通过引用传递。您使用字符串而不是字符串构建器,它将是Hello,因为字符串是immutable。对于intenum等值类型,也没有任何变化。

为简单起见,Value类型是struct,enum,primitive类型,...... 和引用类型是类,但正如我所提到的,有一些像string这样的类是不可变的,事实上,它们将通过值传递。

答案 1 :(得分:3)

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

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

StringBuilder y = new StringBuilder();

并将StringBuilder对象的引用复制到Foo的参数x。

Foo (y);

答案 2 :(得分:3)

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

此外,每种类型都可以传递给方法按价值按参考。 (所以,这意味着实际上有四种方式将参数传递给方法。)

无论您如何传递参考类型(按值或按参考),您都可以更改参考点所指向的值!

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

最后,请注意您正在传递“参考类型”参数“按值”。如果您要传递参考类型按参考,然后将其设置为null,则实际上会销毁与参考相关联的值。 (这与将参数变量设置为方法外的<{1}} 相同。)

您可以在此处找到更全面,更易读的解释:C# Concepts: Value vs Reference Types

答案 3 :(得分:2)

默认情况下,通过引用传递除基本类型之外的任何内容(例如intbyte等)。您正在将相同的StringBuilder实例传递给方法。

答案 4 :(得分:1)

StringBuilder 是一个类,因此它将通过引用传递。

了解详情:Value vs reference types

答案 5 :(得分: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
    }

这里复制了struct,对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)