为了账号安全,请及时绑定邮箱和手机立即绑定

如何通过“引用”将其分配给c#中的类字段?

如何通过“引用”将其分配给c#中的类字段?

C#
守候你守候我 2019-08-19 16:22:16
如何通过“引用”将其分配给c#中的类字段?我试图了解如何通过“引用”分配给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(由Y更新)并不是:X(由Y更新)(由Z更新)正如我所希望的那样。似乎为字段分配“ref参数”会丢失引用。在分配字段时有没有办法保持引用?谢谢。
查看完整描述

3 回答

?
30秒到达战场

TA贡献1828条经验 获得超6个赞

正如其他人所指出的那样,你不能拥有“ref to variable”类型的字段。然而,只知道你不能做到这一点可能并不令人满意; 你可能也想先知道,为什么不知道,其次,如何解决这个限制。

原因是因为只有三种可能性:

1)禁止ref类型的字段

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

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

假设我们允许ref类型的字段。然后你可以做到

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

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

我们喜欢将局部变量存储在临时池中的优化,即使它们是由ref传递的,我们也不喜欢你可能会留下定时炸弹,这可能会导致程序崩溃并在以后死亡。因此,选项一是:没有引用字段。

注意,对于作为匿名函数的封闭变量的局部变量,我们选择option(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#的假设未来版本将支持这些功能; 我有它的原型,它运作良好。但是,这在优先级列表中并不是很高,所以我不会抱有希望。

更新:上面段落中提到的功能最终在C#7中实现了。但是,您仍然无法在某个字段中存储引用。


查看完整回答
反对 回复 2019-08-19
  • 3 回答
  • 0 关注
  • 523 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信