C# 处理引用类型

C# 处理引用类型,c#,reference,types,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;

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

    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的值未更改为changed!。它的原因是什么?我可以认为数组是通过引用传递的,而其他引用类型是通过引用传递的吗
值?

作为参数传递给方法的任何内容都是通过值传递的,对于引用类型,这意味着引用是通过值传递的。因此,你不能将对象更改为另一个对象,但你肯定可以更改其内容,因为这不会更改实际的引用,只是更改其他地方的一些内存

正如您的数组示例所示,您接受数组引用,但不更改它,而是更改数组中的值。这就像获取某个对象并更改属性值一样。您也可以在一个方法中很好地实现这一点

如果要更改字符串(在.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!"
public static void StrPassing(ref string someStr)
ref关键字确保您的方法获得对字符串的实际引用并可以更改它,而不仅仅是引用的副本。这样你就可以用一个全新的对象来替换这个对象

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

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

这也不起作用,因为这样做与将字符串更改为完全不同的字符串完全相同。

任何作为参数传递给方法的内容都是按值传递的,对于引用类型,这意味着引用是按值传递的。因此,你不能将对象更改为另一个对象,但你肯定可以更改其内容,因为这不会更改实际的引用,只是更改其他地方的一些内存

正如您的数组示例所示,您接受数组引用,但不更改它,而是更改数组中的值。这就像获取某个对象并更改属性值一样。您也可以在一个方法中很好地实现这一点

如果要更改字符串(在.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!"
public static void StrPassing(ref string someStr)
ref关键字确保您的方法获得对字符串的实际引用并可以更改它,而不仅仅是引用的副本。这样你就可以用一个全新的对象来替换这个对象

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

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

这也不起作用,因为这样做与将字符串更改为完全不同的字符串完全相同。

您需要做的是将StrPassing的签名更改为如下所示:

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

您需要做的是将StrPassing的签名更改为如下所示:

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

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


一个很好的讨论。

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


很好的讨论。

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

在此代码中:

public static void StrPassing(string someStr)
{
    string otherStr="Changed!";
    someStr=otherStr;
}
public static void NumPassing(int[] a)
{
    a[2] = 115;
}
。。。您正在更改someStr的值。您没有对someStr最初引用的字符串进行任何更改。实际上,您不能这样做,因为字符串是不可变的。如果是StringBuilder,则可以将长度设置为0,然后追加更改

更改someStr的值无效,因为参数ex.str是通过值传递的。所讨论的值是一个引用,但这并不意味着它是通过引用传递的

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

public static void StrPassing(string someStr)
{
    string otherStr="Changed!";
    someStr=otherStr;
}
public static void NumPassing(int[] a)
{
    a[2] = 115;
}
这里您没有更改a的值-您正在更改a引用的数组的内容

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


我有一个更详细的例子来说明这一切。

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

在此代码中:

public static void StrPassing(string someStr)
{
    string otherStr="Changed!";
    someStr=otherStr;
}
public static void NumPassing(int[] a)
{
    a[2] = 115;
}
。。。您正在更改someStr的值。您没有对someStr最初引用的字符串进行任何更改。实际上,您不能这样做,因为字符串是不可变的。如果是StringBuilder,则可以将长度设置为0,然后追加更改

更改someStr的值无效,因为参数ex.str是通过值传递的。所讨论的值是一个引用,但这并不意味着它是通过引用传递的

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

public static void StrPassing(string someStr)
{
    string otherStr="Changed!";
    someStr=otherStr;
}
public static void NumPassing(int[] a)
{
    a[2] = 115;
}
这里您没有更改a的值-您正在更改a引用的数组的内容

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

我有一个很好的解释,这一点我很清楚
t更详细。

不可变并没有使它们变得那么特殊-特别是,编译器不会改变它们的传递方式或类似的任何东西。不可变并没有使它们变得那么特殊-特别是,编译器不会改变它们的传递方式或类似的东西。我不认为按值引用是一个特别有用的术语-将引用传递的内容与按值传递的内容分开。在我看来,领先只是增加了混乱。你是对的。我把它改成了我希望更容易理解的东西。现在更像你的话了。这是我公认的答案。我不认为按值引用是一个特别有用的术语-将引用传递的内容与按值传递的方式分开。在我看来,领先只是增加了混乱。你是对的。我把它改成了我希望更容易理解的东西。现在更像你的话了。这是我公认的答案。德拉特。