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。您应该创建 pttSizeindexSizefactorSize 的常量并将它们用作 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关键字,对吗的主要内容,如果未能解决你的问题,请参考以下文章

C# 中的三个高级参数 ref

out 和 ref + params 的理解

C#中数组作为参数传递的问题

C#在方法调用中,参数按值传递与按引用传递的区别是啥?

C#同样是引用,ref和out到底有什么区别?

在c#中将引用数组作为参数传递[重复]