c# - 如何将 "reference"分配给 C# 中的类字段?

标签 c# reference parameters field

我正在尝试了解如何通过“引用”分配给 C# 中的类字段。

我要考虑以下示例:

 public class X
 {

     public X()
     {
         string example = "X";

         new Y(ref example);

         new Z(ref example);

         System.Diagnostics.Debug.WriteLine(example);
     }

 }

 public class Y
 {

     public Y( ref string example )
     {
         example += " (Updated By Y)";
     }

 }

 public class Z
 {
     private string _Example;

     public Z(ref string example)
     {

         this._Example = example;

         this._Example += " (Updated By Z)";
     }
 }

 var x = new X();

当运行上面的代码时,输​​出是:

X (Updated By Y)

而不是:

X (Updated By Y) (Updated By Z)

正如我所希望的那样。

似乎给一个字段赋一个“ref参数”就失去了引用。

有没有办法在分配给字段时保留引用?

最佳答案

正如其他人所指出的,您不能拥有“引用变量”类型的字段。但是,仅仅知道自己做不到可能并不令人满意;您可能还想首先知道为什么不,其次,如何绕过此限制。

之所以是因为只有三种可能:

1) 不允许引用类型的字段

2) 允许引用类型的不安全字段

3) 不要将临时存储池用于局部变量(又名“堆栈”)

假设我们允许 ref 类型的字段。那么你可以做

public ref int x;
void M()
{
    int y = 123;
    this.x = ref y;
}

现在可以在 M 完成后访问 y。这意味着要么我们在情况 (2) 中——访问 this.x 将崩溃并可怕地死去,因为 y 的存储不再存在——或者我们在情况 (3) 中,并且本地 y 存储在垃圾收集堆中,而不是临时内存池中。

我们喜欢将局部变量存储在临时池中的优化,即使它们是由 ref 传递的,我们讨厌这样的想法,即您可以在周围留下一个定时炸弹,这可能会使您的程序崩溃并在以后死亡。因此,选项一是:没有 ref 字段。

请注意,对于作为匿名函数的封闭变量的局部变量,我们选择选项 (3);这些局部变量不会分配到临时池之外。

这让我们想到了第二个问题:您如何解决这个问题?如果您想要 ref 字段的原因是为另一个变量创建 getter 和 setter,那是完全合法的:

sealed class Ref<T>
{
    private readonly Func<T> getter;
    private readonly Action<T> setter;
    public Ref(Func<T> getter, Action<T> setter)
    {
        this.getter = getter;
        this.setter = setter;
    }
    public T Value { get { return getter(); } set { setter(value); } }
}
...
Ref<int> x;
void M()
{
    int y = 123;
    x = new Ref<int>(()=>y, z=>{y=z;});
    x.Value = 456;
    Console.WriteLine(y); // 456 -- setting x.Value changes y.
}

好了。 y 存储在 gc 堆上,x 是一个具有获取和设置 y 能力的对象。

请注意,CLR 确实支持 ref 局部变量和 ref 返回方法,但 C# 不支持。也许假设的 C# future 版本将支持这些功能;我已经制作了它的原型(prototype)并且效果很好。但是,这在优先级列表中并不是真正的高,所以我不会抱太大希望。

更新:上一段中提到的功能最终在 C# 7 中真正实现了。但是,您仍然不能在字段中存储 ref。

关于c# - 如何将 "reference"分配给 C# 中的类字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2980463/

相关文章:

c# - 在 where 子句 LinQ 中使用 let 的结果

C# |在 SqlCommand 查询中使用参数

java - Java是按引用返回还是按值返回

c# - 为什么在创建和返回新结构时出现此错误?

c++ - Delphi与C++dll通信(参数)

C++ 模板 : Function as Template Class Parameter

mysql - 如何通过命令行调整mysql参数的大小

c# - 包含 LINQ 查询的重构方法

c# - 什么是部署简单服务/守护进程(具有简单 UI)的最佳跨平台方法(Windows/Mac)

c++ - 为什么C++中没有 "NULL reference"?