添加.net COM包装器按值而不是ref来缓存

时间:2010-01-07 10:50:23

标签: c# com pass-by-reference pass-by-value

在我的代码中,我通过COM接口实例化一个遗留的Delphi对象。 这个类需要多次实例化,因此为了降低实例化它的开销,我将其缓存在70%的所有调用都具有公共结果对象的位置。

但是,当我在缓存对象后更改对象时,更改也会保留在缓存中。这让我觉得COM包装器实例是由ref而不是值传递的 如何确保缓存中的对象是通过值传递而不是通过ref传递?

2 个答案:

答案 0 :(得分:0)

我认为,如果可以做的话,你需要显式克隆对象的副本然后缓存副本。例如,请参阅MemberwiseClone方法,以及Cloning objects in C#的答案中提到的其他方法。

答案 1 :(得分:0)

首先,这需要吗?

我不是“测量解决所有性能问题”的倡导者,但在你的情况下,你应该这样做。

实例化COM对象(在第一次调用惩罚之后)的开销非常低 - 记住它的设计是为了在15年前的计算机上提供许多小对象。我假设.NET开销不多 - 所以问题是对象自己的初始化。

您可以通过在紧密循环中实例化1000个对象来轻松检查(抛弃第一个调用,它可能非常昂贵并且会破坏平均值)

COM对象本质上是通过引用
COM对象没有“按值传递”,因为它们的基本接口是指向实例的引用计数指针,COM不公开通用的“克隆”方法。

可能的解决方案:写时复制
如果只有if实例化真的昂贵,并且大多数调用可以通过默认实例完成,则可以实现写时复制方案。

您需要创建一个包装类,该类包含对默认实例的引用,以及对初始化为0的私有实例的引用。

只要私有实例是null,所有getter函数都转发到默认实例,其他的,它们转发到私有实例。

每个setter / mutator调用都会转发到私有实例,并在它不存在时创建它。

这会将私有实例的创建延迟到第一个变异调用。但是,您必须包装此组件的所有感兴趣的接口。