zoukankan      html  css  js  c++  java
  • 让泛型类支持数值计算

    class Ref<T>
    {
        public T Value;
        public Ref<T>()
        {
        }
        public Ref<T>(T value)
        {
            this.Value = value;
        }
    }

    Then use it like this:

    class A
    {
        Ref<int> x;
        public A(Ref<int> x)
        {
            this.x = x;
        }
        public void Increment()
        {
            x.Value++;
        }
    }
    
    ...
    
    Ref<int> x = new Ref<int>(7);
    A a = new A(x);
    a.Increment();
    Debug.Assert(x.Value == 8);

    Note that the Ref<T> class here is a reference to a value - not a reference to a variable. If you want a reference to a variable, use Eric Lippert's solution (as pointed out by Filip).

    public class StringWrapper
     {
       public string s;
       public StringWrapper(string s)
       {
         this.s = s;
       }
    
       public string ToString()
       {
         return s;
       }
     }
    
     public class X
     {
      public X()
      {
       StringWrapper example = new StringWrapper("X");
       new Z(example)
       System.Diagnostics.Debug.WriteLine( example );
      }
     }
    
     public class Z
     {
      private StringWrapper _Example;
      public Z( StringWrapper example )
      {
       this._Example = example;
       this._Example.s += " (Updated By Z)";
      }
     }

    As others have noted, you cannot have a field of "ref to variable" type. However, just knowing that you cannot do it is probably unsatisfying; you probably also want to know first, why not, and second, how to get around this restriction.

    The reason why is because there are only three possibilities:

    1) Disallow fields of ref type

    2) Allow unsafe fields of ref type

    3) Do not use the temporary storage pool for local variables (aka "the stack")

    Suppose we allowed fields of ref type. Then you could do

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

    and now y can be accessed after M completes. This means that either we're in case (2) -- accessing this.x will crash and die horribly because the storage for y no longer exists -- or we're in case (3), and the local y is stored on the garbage collected heap, not the temporary memory pool.

    We like the optimization that local variables be stored on the temporary pool even if they are being passed by ref, and we hate the idea that you could leave a time bomb around that could make your program crash and die later. Therefore, option one it is: no ref fields.

    Note that for local variables that are closed-over variables of anonymous functions we choose option (3); those local variables are not allocated out of the temporary pool.

    Which then brings us to the second question: how do you get around it? If the reason you want a ref field is to make a getter and setter of another variable, that's perfectly legal:

    sealedclassRef<T>{privatereadonlyFunc<T> getter;privatereadonlyAction<T> setter;publicRef(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 =newRef<int>(()=>y, z=>{y=z;});
        x.Value=456;Console.WriteLine(y);// 456 -- setting x.Value changes y.}

    And there you go. y is stored on the gc heap, and x is an object that has the ability to get and set y.

    Note that the CLR does support ref locals and ref returning methods, though C# does not. Perhaps a hypothetical future version of C# will support these features; I have prototyped it and it works well. However, this is not real high on the priority list, so I wouldn't get my hopes up.

  • 相关阅读:
    为什么今日头条是技术牛人收割机(FW)
    独家|浅谈用户行为数据的价值挖掘(PPT)(FW)
    深度学习笔记
    "堕落"的头条,还是"不堪"的民众?
    理解传统企业的问题与困惑
    人工智能在医疗领域究竟要怎么玩?(FW)
    佟崴嵬
    youtube true view的逻辑
    AI第一性原理
    域对象的属性和请求的转发重定向
  • 原文地址:https://www.cnblogs.com/zeroone/p/3715350.html
Copyright © 2011-2022 走看看