c#传递引用对象作为参数的时候就没有必要用ref关键字,对吗
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c#传递引用对象作为参数的时候就没有必要用ref关键字,对吗相关的知识,希望对你有一定的参考价值。
我是这样理解的,我们在传递string,int这样的值类型的时候,如果必要则需要添加ref,但是对于引用对象来说,加不加ref都始终是传的这个地址,所以对于引用对象来说就不需要添加ref修饰词了。不知道对不对,请指点。
传递引用对象时添加ref关键字和不添加还是有不同的。不添加ref关键字时,作为方法参数的形参与实际传入的实参实际上是两个对象,在栈中有两个地方分别保存它们的名字,假设形参叫A,实参叫B。只是引用对象保存的本来就是地址,所以这两个对象的值“恰好”指向堆中的同一个地方,假设这个地方叫C,对这两个对象的值进行修改实际上是修改C,所以都会影响到另一个对象;假如我们对A重新赋值,相当于让A指向了堆中另一个地方D,这个操作当然不会对B有任何影响。此时我们修改AB的值相当于修改CD,相互之间也就没有什么关联了。
添加ref关键字时,方法将实参在栈中的位置当做实参的位置,此时形参就是实参,只是叫法不同。此时对形参的任何操作都会反映到实参上,因为两者本来就是同一个对象。可以参考下面的例子:
class Program
static void Main(string[] args)
Test a = new Test();
a.Value = 1;
Test b = a;
Change(b);//a.value值为1,b.value值为1;形参重新赋值没有影响到实参,方法结束后形参的生命周期也随之结束
b.Value = 2;//a.value值为2,b.value值为2;a和b指向同一地址
Change(ref b);//a.value值为2,b.value值为0;此时形参就是实参,只是叫法不一样
b.Value = 3;//a.value值为2,b.value值为3;两者已经指向不同地址了,相互之间不会影响
ReadKey();
static void Change(Test test)
test = new Test();
static void Change(ref Test test)
test = new Test();
class Test
public int Value;
参考技术A 如果你是要修改引用对象的属性可以不加ref,如果你是想改变这个引用本身,就必须加了。如:
public
class
Test
public
int
t;
public
Test(int
t)
this.t
=
t;
static
void
Main(string[]
args)
Test
t
=
new
Test(2);
ChangeProperty(t);
Console.WriteLine(t.t);
ChangeSelf(t);
Console.WriteLine(t.t);
ChangeSelf2(ref
t);
Console.WriteLine(t.t);
static
void
ChangeProperty(Test
t)
t.t
=
10;
static
void
ChangeSelf(Test
t)
t
=
new
Test(20);
static
void
ChangeSelf2(ref
Test
t)
t
=
new
Test(20);
参考技术B 加了ref 当方法试图改变参数名所对应的引用地址时,不会触发引用拷贝。如果不加ref那么修改参数名所对应的引用地址,那么就会触发引用拷贝。多线程模式下不建议加ref。
你可以这么理解:
“=”赋值运算符,在方法中,对于值类型(结构体)默认是拷贝值的形式,而对于对象(object)是拷贝引用的形式(这里的对象是指直接继承object的子类)。
加ref 会检测赋值运算符“=”所对应的原始引用并尝试修改。如果不加ref则遇到“=”时则拷贝引用(其实就是声明新的引用并赋值)。
所以:
你问的加不加ref,关键在于是否使用“=”来修改方法参数所对应的地址,如果方法中没有使用“=”来修改方法参数的地址则不用纠结是否加ref,如果你加了ref,编译器看到你在方法中有用“=”来修改地址,那么编译成IL之后也会忽略掉。
在c#中将引用数组作为参数传递[重复]
【中文标题】在c#中将引用数组作为参数传递[重复]【英文标题】:Pass reference array as argument in c# [duplicate] 【发布时间】:2021-12-05 07:56:18 【问题描述】:亲爱的,
我创建了一个方法,该方法将在使用 ref 选项填充三个数组后检索它们
出现以下错误“System.IndexOutOfRangeException: 'Index was outside the bounds of the array.'”
代码如下。我该如何解决它
namespace ConsoleApp9
class Program
public static int getarrays(ref string[] patternName, ref int[] loadindex, ref double[] loadFactor)
int status = 0;
for (int i = 0; i < 4; i++)
patternName[i] = "test";
for (int i = 0; i < 5; i++)
loadindex[i] = i;
for (int i = 0; i < 8; i++)
loadFactor[i] = i/10;
return status;
static void Main(string[] args)
string[] ptt = new string[1];
int[] index = new int[1];
double[] factor = new double[1];
getarrays(ref ptt,ref index, ref factor);
【问题讨论】:
【参考方案1】:您正在传递固定大小为1
的数组。在您的方法中,您将迭代 4、5 和 8 次,而您的 arrays
的长度为 1。您应该创建 pttSize
、indexSize
和 factorSize
的常量并将它们用作 arrays
大小和loops
长度。
【讨论】:
【参考方案2】:您将长度为 1 的数组传递给函数,然后尝试访问大于 0 的索引。
调整您的 Main
方法以传递正确长度的数组:
string[] ptt = new string[4];
int[] index = new int[5];
double[] factor = new double[8];
【讨论】:
【参考方案3】:您的数组的大小均为 1,但您的循环分别为 4、5 和 8。相反,请在循环中使用数组的 Length
属性:
for (int i = 0; i < patternName.Length; i++)
patternName[i] = "test";
这很有帮助,因为数组的大小只位于一个位置(在创建数组时)。
【讨论】:
以上是关于c#传递引用对象作为参数的时候就没有必要用ref关键字,对吗的主要内容,如果未能解决你的问题,请参考以下文章