处理参考类型

时间:2009-11-10 07:11:06

标签: c# reference types

当引用变量可以通过引用传递时:

    class Example
    {
        public string str="Demo";

        public int[] intValues={1,3,4,5};

       public static void StrPassing(string someStr)
        {
            string otherStr="Changed!";
            someStr=otherStr;
        }

        public static void NumPassing(int[] a)
        {
            a[2] = 115;
        }

    }


       static void Main(string[] args)
        {
            Example ex = new Example();
            Example.StrPassing(ex.str);
            Example.NumPassing(ex.intValues);

            foreach (int i in ex.intValues)
            {
                Console.WriteLine(i);
            }

            Console.WriteLine(ex.str);
            Console.ReadLine();
        }

intValues[2]的值在传递引用时更改为115。但字符串“str”(demo)的值不会更改为“已更改!”。什么是它的原因?。我可以把它作为数组通过引用传递,其他引用类型传递 值?

4 个答案:

答案 0 :(得分:5)

无论传递给方法的是什么,因为参数是通过值传递的,对于引用类型,这意味着引用是按值传递的。因此,您无法将对象更改为另一个,但您可以确定地更改其内容(因为这不会更改实际引用,只会更改其他地方的内存)。< / p>

正如您在数组中的示例所示,您将获取数组引用(但不要更改它)并更改数组中的值。这就像获取一些对象并更改属性值一样。你也可以在一种方法中做到这一点。

如果要更改字符串(.NET中的不可变对象),则需要使用ref参数:

public static void StrPassing(ref string someStr)
{
    string otherStr="Changed!";
    someStr=otherStr;
}

并称之为:

string foo = "foo";
StrPassing(ref foo);
Console.WriteLine(foo); // should print "Changed!"

ref关键字确保您的方法获得对字​​符串的实际引用并可以更改它,而不仅仅是引用的副本。那么你可以用一个全新的替换对象。

回到您的阵列:您也很难将传递的数组更改为完全不同的数组:

public static void NumPassing(int[] a)
{
    a = new int[15];
}

也不会起作用,因为然后你会尝试将字符串更改为完全不同的字符串。

答案 1 :(得分:3)

您需要区分更改变量引用的对象和更改*对象的内容“。

在此代码中:

public static void StrPassing(string someStr)
{
    string otherStr="Changed!";
    someStr=otherStr;
}

...您正在更改someStr的值。您没有对someStr最初引用的字符串进行任何更改。实际上,你不能因为字符串是不可变的。 (如果是StringBuilder,您可以将长度设置为0然后追加“已更改!”。

更改someStr的值无效,因为参数(ex.str)是按值传递的。 (有问题的值引用,但这并不意味着它通过引用传递。)

现在将其与此代码进行比较:

public static void NumPassing(int[] a)
{
    a[2] = 115;
}

此处您更改a的值 - 您正在更改a引用的数组的内容。

简而言之,除非您使用ref / out,否则参数将按值传递 - 但对于引用类型,该值只是一个引用。

我有一个article on parameter passing,可以更详细地介绍所有这些内容。

答案 2 :(得分:1)

您需要做的是将StrPassing的签名更改为:

public static void StrPassing(ref string someStr)

答案 3 :(得分:0)

字符串在C#中是特殊的。它们是不可变的引用类型,使它们表现出与值类型类似的行为。

Here's一个很好的讨论。