【问题标题】:How to pass this by ref in C#?如何在 C# 中通过 ref 传递它?
【发布时间】:2011-06-29 22:40:46
【问题描述】:

在我的一个类 (ClassA) 中,我想创建另一个类 (ClassB) 的相关实例,为它提供对启动它创建的对象的引用。所以我为 ClassB 提供了一个带有(ref ClassB master)参数的构造函数。但在 ClassA 中,我不能只调用 var slave = new ClassB(ref this)。如何实现?

【问题讨论】:

  • 我不完全确定您要在这里完成什么。您确实知道 .NET 中的引用类型已经通过指针实现,对吧? new ClassB(this) 将当前对象的引用传递回ClassB 的构造函数。为什么需要ref
  • 我不认为你真的打算通过参考传递thisfoo(ref bar) 表示 foo 可以将 bar 指向其他地方。 this 是一个您无法更改的常量,并且在大多数情况下您只想保留它的一个值。

标签: c# .net reference this


【解决方案1】:

ref关键字引起Pass by Reference语义——即如果变量在被调用函数中重新赋值,它会重新赋值变量 在调用者中也是如此。

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

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

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

但是,传递 reference 不应与 Pass by Object [Sharing]1 语义混淆。传递对象意味着如果传递了一个对象,那个对象就传递了:该对象被复制/克隆/复制。 如果对象发生变异,则对象发生变异。所有Reference Types在C#中都具有传递对象语义,除非ref或@使用 987654331@。 (class 关键字声明了一个新的引用类型,如帖子中的情况)。

另一方面,Value Types(例如struct),包括intGuidKeyValuePair<K,V>,具有Pass by Value 语义——在这种情况下,一个副本因此,如果值被修改,只有值结构(它是一个副本)会改变

快乐编码


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

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

【讨论】:

    【解决方案2】:

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

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

    因此,您既不需要在构造函数中也不需要在实例化中使用 ref 关键字:

    public ClassB(ClassA master)
    {
    }
    
    var slave = new ClassB(this);
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 不,它是按值传递的,但是你传递的值是一个引用!
      • @LukeH - 正确,这就是我想说的:)
      【解决方案4】:

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

      【讨论】:

      • 您的意思是“所有引用类型”。
      • 所有类型都是按值传递的(除非你使用refout修饰符)。
      • @LukeH - 我不明白你的意思 - 你的意思是说指针是按值传递的?
      • 是的。是通过值还是通过 ref 传递与传递 ref 类型还是值类型是正交的。
      【解决方案5】:

      您不能更改 this 指针,这是 ref 关键字允许的。为什么不能这样声明ClassB?

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

      【讨论】:

      • 在这种情况下不会复制任何内容吗? classB.classA 会指向原来的 ClassA 实例吗?
      • 是的,classB.m_classA 将指向原来的 ClassA 实例。
      猜你喜欢
      • 1970-01-01
      • 2020-06-08
      • 2010-10-09
      • 1970-01-01
      • 2011-04-29
      • 2011-02-03
      • 1970-01-01
      • 1970-01-01
      • 2012-09-16
      相关资源
      最近更新 更多