代码之家  ›  专栏  ›  技术社区  ›  Martin Hennings

属性get调用何时创建引用类型的本地副本?如何避免?

  •  0
  • Martin Hennings  · 技术社区  · 14 年前

    在班上 fooBase SomeProperty barBase ,我有一个类型为 :

    public class fooBase 
    {
        public object SomeProperty { get; set; }
    }
    
    public class barBase
    {
        protected fooBase _foo;
    }
    

    很明显,在巴巴多斯我可以通过 _foo.SomeProperty = whatever; .

    现在在派生类中 fooChild 派生类基于一些不重要的逻辑 barChild 操作。barChild构造函数获取fooChild的实例并存储它。

    public class fooChild : fooBase { /* someLogic */ }
    
    public class barChild : barBase
    {
        public barChild(fooChild foo)
        {
            _foo = foo; // foo of [fooChild] type stored in _foo of [fooBase] type.
        }
    
        protected fooChild _getFoo // cast via 'as' to access fooChild logic
        { get { return _foo as fooChild; } }
    }
    

    _foo as fooChild (哪个 _getFoo

    问题 :将 get { return ... as ... } SomeFunction()

    public class somewhereElse : barChild
    {
        public void SomeFunction()
        {
            _getFoo.SomeProperty = new object();
            // now barBase:_foo.SomeProperty is still old object?
        }
    }
    

    如果是,我怎样才能避免呢?
    如果没有,我怎么知道?

    2 回复  |  直到 14 年前
        1
  •  0
  •   Kikaimaru    14 年前

    (MySubClass)myInstance
    
    myInstance as MySubClass
    

    这几乎是一样的(niether将创建新实例)

        2
  •  2
  •   Jon Hanna    14 年前

    复制引用类型的唯一时间是在调用主动复制的方法或属性时。Clone()就是一个明显的例子(除了一些例外,对于像string这样的不可变类型,Clone()只返回相同的对象并假装它是一个新的对象是安全的,因为任何东西都不能改变)。

    as 总是一种身份塑造。 x = obj as T

    if(obj is T)
      x = (T)(object)obj;
    else
      x = null;
    

    我的理由是 (T)(object) 在那里而不仅仅是 (T) 有时会存在一个隐式的cast操作符来在两种类型之间进行转换,并且 可以 object 不会(除非有人对cast操作符很愚蠢-我很确定编译器会阻止他们,如果他们那么愚蠢的话,但是这种情况太愚蠢了,我不想去测试,只是不要在对象之间写cast)。

    如果要测试一个对象是否与另一个对象相同,请使用 ReferenceEquals ,这仅针对标识进行比较,即使覆盖了Equals,或者参数是装箱的值类型。