2009-12-08 63 views
6

我试图设计一个类,它可以更新对一个对象(类之外)的引用销毁。在c中存储引用#

所以,基本上你创建了这个对象的一个​​实例,并传递给它一个引用类型(以任何方式,构造函数等),然后破坏对象原始引用已经改变为由对象创建的引用。

如果我通过引用传递引用(比如在构造中),我无法想出一个方法来存储此引用(作为引用)以供析构函数更新它吗? 例如(伪):

class Updater 
{ 
    object privateReference; 
    public Updater(ref object externalReference) 
    { 
     privateReference = externalReference; //is privateReference now a new reference to the original object? 
    } 

    ~Updater() 
    { 
     privateReference = new object(); //therefore this isn't 'repointing' the externalReference 
    } 
} 

这里的关键是我并不想发生变异从这个类我想原来的“外部”对象“重新指向”它,或者如果你愿意初始化它。

+0

如果你正在销毁你的物体,为什么'重新命名'一个内部字段也会被销毁呢? – Oded 2009-12-08 11:37:44

+0

即时通讯不试图重新命名内部领域,这是重点。我试图重新指出它指向的东西......如果这是有道理的。 – 2009-12-08 11:40:24

+2

将一个字段(或任何其他基于堆的存储,如数组元素)存储到一个变量的ref是绝对合法的。原因是:ref可能是堆栈中一个局部变量的引用,它的生存期比存放ref的存储区更短,从而导致ref无效。我们可以(1)使裁判不安全和脆弱,比如C++,或者(2)限制裁判的存储并保持裁判总是安全的,或者(3)从不在堆叠中存储东西。我们选择了(2)。 – 2009-12-08 14:42:25

回答

7

基本上,你不能这样做。 ref只适用于该方法本身。

你一直都不清楚你想用什么 - 你能给我们更多的信息,所以我们可以建议替代设计吗?任何依赖于终结器的东西都是令人头痛的,说实话...

+0

正是我害怕的!这是一个我曾经在C++中看到的剖析器的实现...基本上你创建了一个Profiler实例(传入一个变量,在事件探查器落入范围之外时,这个变量被充满(在本例中)是一个时间跨度对象。显然依靠指针分配... – 2009-12-08 11:43:58

+1

当变量超出范围时终止器不运行,所以这是它不起作用的另一个原因... – 2009-12-08 11:48:20

1

请注意,使用Finalizer这样的功能与C++中的析构函数并不相同。

当最后一个参考死亡(也许它超出范围)时,对象将进入Finalizer队列。 GC确定何时调用终结器,并且在最后一次参考死亡后很长时间。

4

这将不起作用,因为构造函数参数的ref方面仅适用于构造函数内部。

我会做的是给构造函数一个委托,可以用来更新有问题的东西。此外,您应该使用IDisposable(与using块一起)而不是终结器;终结器不应该触摸托管对象(它们旨在释放非托管对象)。

class Updater : IDisposable 
{ 
    Action<object> setter; 

    public Updater(Action<object> setter) 
    { 
     this.setter = setter; 
    } 

    public Dispose() 
    { 
     setter(new object()); 
    } 
} 
+0

这实际上是我正在调整的示例的方法需要..这是一个选项,但我想稍微解耦它。 – 2009-12-08 11:45:35