C# · 12月 31, 2021

c# – 通过引用传递对象vs值

在我深入研究设计课程之前,我只想检查我对C#的处理方法的理解.我目前的理解是:

> Struct是一个值类型,意味着它实际上包含在其中定义的数据成员.
> Class是一个引用类型,这意味着它包含对在其中定义的数据成员的引用.
>方法签名通过值传递参数,这意味着值的副本将传递给方法的内部,从而使大型数组和数据结构变得昂贵.
>使用ref或out关键字定义参数的方法签名将通过引用传递参数,这意味着提供了指向对象的指针.

我不明白的是当我调用一个方法,实际发生的情况下会发生什么.是否调用new()?它只是自动复制数据?或者它实际上只是指向原始对象?使用ref和out如何影响这个?

解决方法

What I don’t understand is what happens when I invoke a method,what actually happens. Does new() get invoked? Does it just automagically copy the data? Or does it actually just point to the original object? And how does using ref and out affect this?

简短的答案:

空构造函数不会自动调用,它实际上只是指向原始对象.
使用ref和out不影响这一点.

长的答案:

我认为这将更容易理解C#如何处理传递参数到一个函数.
其实一切都是通过价值传递的
真?!一切按价值?
是!一切!

当然,传递类和简单类型对象之间必须有一些区别,比如整数,否则,这将是一个巨大的回报.

那么事情是,当你将一个对象的类实例传递给一个函数时,幕后的真正传递给函数的是指向该类的指针.指针当然可以通过值传递而不会导致性能问题.

其实,一切都是通过价值的传递;这只是当时
你是“传递一个对象”,你实际上是通过一个引用
对象(并且您通过值传递该引用).

一旦我们在函数中,给定参数指针,我们可以关联通过引用传递的对象.
你实际上不需要为此做任何事情,你可以直接关联到作为参数传递的实例(如前所述,这个整个过程在幕后完成).

理解这之后,你可能明白空构造函数不会被自动调用,它实际上只是指向原始对象.

编辑:

对于out和ref,它们允许函数更改参数的值,并将该更改持久保留在函数的范围之外.
简而言之,对于值类型使用ref关键字将执行如下操作:

int i = 42;foo(ref i);

将c翻译成:

int i = 42; int* ptrI = &i;foo(ptrI)

而省略ref将简单地转换为:

int i = 42;foo(i)

使用这些关键字作为引用类型对象,将允许您将内存重新分配给传递的参数,并使重新分配持久存在于该函数的范围之外(更多详细信息请参考MSDN page)

边注:ref和out之间的区别是,out确保被调用的函数必须为out参数分配一个值,而ref没有这个限制,然后你应该通过自己分配一些默认值来处理它,因此ref ref参数的初始值对函数很重要,可能会影响其行为.