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