在我的代码中,我通过COM接口实例化一个遗留的Delphi对象。 这个类需要多次实例化,因此为了降低实例化它的开销,我将其缓存在70%的所有调用都具有公共结果对象的位置。
但是,当我在缓存对象后更改对象时,更改也会保留在缓存中。这让我觉得COM包装器实例是由ref而不是值传递的 如何确保缓存中的对象是通过值传递而不是通过ref传递?
答案 0 :(得分:0)
我认为,如果可以做的话,你需要显式克隆对象的副本然后缓存副本。例如,请参阅MemberwiseClone
方法,以及Cloning objects in C#的答案中提到的其他方法。
答案 1 :(得分:0)
首先,这需要吗?
我不是“测量解决所有性能问题”的倡导者,但在你的情况下,你应该这样做。
实例化COM对象(在第一次调用惩罚之后)的开销非常低 - 记住它的设计是为了在15年前的计算机上提供许多小对象。我假设.NET开销不多 - 所以问题是对象自己的初始化。
您可以通过在紧密循环中实例化1000个对象来轻松检查(抛弃第一个调用,它可能非常昂贵并且会破坏平均值)
COM对象本质上是通过引用
COM对象没有“按值传递”,因为它们的基本接口是指向实例的引用计数指针,COM不公开通用的“克隆”方法。
可能的解决方案:写时复制
如果只有if实例化真的昂贵,并且大多数调用可以通过默认实例完成,则可以实现写时复制方案。
您需要创建一个包装类,该类包含对默认实例的引用,以及对初始化为0的私有实例的引用。
只要私有实例是null
,所有getter函数都转发到默认实例,其他的,它们转发到私有实例。
每个setter / mutator调用都会转发到私有实例,并在它不存在时创建它。
这会将私有实例的创建延迟到第一个变异调用。但是,您必须包装此组件的所有感兴趣的接口。