通过引用与值传递对象

本文关键字:对象 值传 引用 | 更新日期: 2023-09-27 18:20:37

在深入设计类之前,我只想检查一下我对C#处理问题的方式的理解。我目前的理解是:

  • Struct类型,这意味着它实际上包含在中定义的数据成员
  • Class引用类型,这意味着它包含对中定义的数据成员的引用。

  • 方法签名通过传递参数,这意味着该值的副本会传递到方法内部,这对于大型数组和数据结构来说成本高昂。

  • 使用refout关键字定义参数的方法签名将通过引用传递参数,这意味着将提供指向对象的指针

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

通过引用与值传递对象

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

简短的回答是:

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

答案很长:

我认为理解C#如何处理向函数传递参数会更容易
实际上,所有都通过值
真的吗?!一切都按价值衡量
对每件事

当然,传递类和简单类型对象(如Integer)之间一定有某种区别,否则,这将是性能上的一个巨大倒退。

问题是,在幕后,当你将对象的类实例传递给函数时,真正传递给函数的是指向该类的指针。当然,指针可以按值传递,而不会引起性能问题。

事实上,一切都是通过价值传递的;只是当你在"传递一个对象",实际上是在传递对它的引用对象(并且您通过值传递该引用)。

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

了解了这一点之后,您可能会明白,空构造函数不会被自动调用,而且它实际上只是指向原始对象。


编辑:

至于outref,它们允许函数更改参数的值,并使该更改在函数范围之外持续存在
简而言之,对值类型使用ref关键字的作用如下:

int i = 42;
foo(ref i);

将在c++中翻译为:

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

而省略ref将简单地翻译为:

int i = 42;
foo(i)

引用类型对象使用这些关键字,将允许您将内存重新分配给传递的参数,并使重新分配在函数范围之外持续存在(有关更多详细信息,请参阅MSDN页面)

旁注:
ref和out的区别在于,out确保被调用的函数必须为out参数赋值,而ref没有这个限制,然后你应该通过自己赋值来处理它,因此,ref意味着参数的初始值对函数很重要,可能会影响它的行为。

将值类型变量传递给方法意味着将变量的副本传递给方法。在方法内部对参数进行的任何更改都不会影响存储在变量中的原始数据。

如果希望被调用的方法更改参数的值,则必须使用ref或out关键字通过引用传递。

按值传递引用类型参数时,可以更改引用所指向的数据,例如类成员的值。但是,不能更改引用本身的值;也就是说,不能使用相同的引用为新类分配内存,并使其在块外持久存在。为此,请使用ref(或out)关键字传递参数。

参考:传递参数(C#)

不幸的是,在C#或VB.NET中没有按值传递对象的方法。我建议您传递,例如,NewClass1(Object1),其中Object1是Class1的实例。要做到这一点,您必须编写自己的New方法,但至少可以为Class1提供一个简单的值传递功能。