如何在C#中通过ref传递

本文关键字:ref 传递 | 更新日期: 2023-09-27 18:00:48

在我的一个类(ClassA)中,我想创建另一个类的相关实例(ClassB),为它提供对发起创建它的对象的引用。因此,我为ClassB提供了一个采用(ref ClassB parent)参数的构造器。但在ClassA中,我不能只调用var child=new ClassB(引用this)。如何实现?

如何在C#中通过ref传递

ref关键字会导致传递引用语义-也就是说,如果变量在被调用函数中被重新分配,它也会在调用方中重新分配

显然,只有当变量2(可以重新赋值)作为参数直接传递时,这才有效,如果传递任意表达式,这将不起作用。在这种情况下,this不是一个变量,而是一个不能重新赋值的特殊表达式,因此不能使用。

因此,这将起作用:(但请查看其他答案,并继续阅读为什么这可能是不需要的和/或只是愚蠢的。)

var me = this;
var other = new ClassB(ref me);

但是,不应将"按ref传递"与"按对象传递[Sharing]1"语义混淆。传递对象意味着如果传递了对象,则传递对象:对象不是复制/克隆/复制的如果对象发生突变,则该对象非使用refout,否则所有引用类型在C#中都具有传递对象语义。(class关键字声明了一个新的引用类型,就像文章中的情况一样)。

另一方面,值类型(例如struct),包括intGuidKeyValuePair<K,V>,具有传递值语义-在这种情况下,会生成一个副本,因此,如果修改了值,则只有值结构(它是一个副本)会更改

快乐编码


1Underneath C#/.NET通过按值传递对对象的引用来实现按对象传递。然而,上面的规则正确地描述了可观察的语义和效果。

2与C#不同,C#只允许变量与ref一起使用,VB.NET允许使用Properties。VB.NET编译器在编译期间自动创建临时变量和属性的隐式读/写指令。

ref指的是变量引用,而不是对象引用。

如果只想传递对对象的引用,则不需要ref关键字。对象已经是引用类型,所以它们的引用是通过值传递的。对象本身不会被复制。

因此,在构造函数和实例化中都不需要ref关键字:

public ClassB(ClassA parent)
{
}
var child = new ClassB(this);

在这种情况下,您不需要通过ref。如果您正在传递ClassB(this),那么它将通过引用传递,而不是通过值传递。对传递到类B的构造函数中的类A实例所做的任何更改也将应用于类A。

您真的需要ref关键字吗?所有类型基本上都是通过引用传递的,所以如果你有ClassB以ClassA作为构造函数参数,只需传递新的ClassB(this),就不需要使用引用。

不能更改this指针,这是ref关键字允许的。你为什么不能这样申报B类?

ClassA m_classA;
public ClassB(ClassA classA)
{
   m_classA = classA;
}