0

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

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

4

2 回答 2

0

我认为,如果可能的话,您需要显式克隆对象的副本,然后缓存该副本。例如,请参阅C# 中克隆对象的MemberwiseClone答案中提到的方法和其他方法。

于 2010-01-07T11:04:34.603 回答
0

首先,这需要吗?

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

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

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

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

可能的解决方案:Copy-on-Write
如果仅当实例化真的很昂贵,并且大多数调用可以通过默认实例完成,您可以实现一个 copy-on-write 方案。

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

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

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

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

于 2010-01-07T11:23:37.533 回答