代码之家  ›  专栏  ›  技术社区  ›  David Brown Muad'Dib

如何避免在整个地方创建新的包装器对象?

  •  2
  • David Brown Muad'Dib  · 技术社区  · 15 年前

    我有各种各样的课程 IntPtr .它们不存储自己的数据(指针除外),而是使用属性和方法使用非托管库在指针处公开数据。它工作得很好,但我已经到了需要能够从其他包装器对象引用这些包装器对象的地步。例如:

    public class Node {
        private IntPtr _ptr;
    
        public Node Parent {
            get { return new Node(UnmanagedApi.GetParent(_ptr)); }
        }
    
        internal Node(IntPtr ptr) {
            _ptr = ptr;
        }
    }
    

    现在,我可以简单地返回 new Node(parentPtr) (如上所述),但有可能拥有数万个节点。这不是个坏主意吗,因为多个包装器对象最终可能引用同一个 指针 ?

    我能做些什么来解决这个问题?我想用静电 KeyedCollection 使用每个的类 国际乒乓球联合会 作为钥匙。所以,不是返回一个新的 Node 每次我都能查到。但这会带来线程问题,对吗?

    有更好的方法吗?

    3 回复  |  直到 15 年前
        1
  •  1
  •   Paolo    15 年前

    我能看到的最大问题是谁负责删除指针引用的对象?

    重用同一个对象不一定是线程问题,但是如果您负责调用非托管对象上的delete,则需要在对象中实现某种引用计数。

    如果对象是只读的,使用具有相同指针的多个对象可能更容易。如果它们具有可以更改的状态,那么如果多个对象持有指向该状态的指针,那么您需要了解进行更改的影响。

    你可能还想看看c++/CLI(托管C++)来在C语言和非托管库之间提供一个层,并在那里进行翻译/操作的艰苦工作,并提供一个更简单的API来处理。

        2
  •  1
  •   Larry Watanabe    15 年前

    整个代码看起来不正确。

    使用getparent函数似乎意味着您有一个类似树的结构。让我对您的代码做一些猜测,它们可能是错误的。

    1. 您希望广泛使用UnmanagedAPI,并且不希望在.NET代码中复制此代码。

    2. 您只想通过访问未损坏的代码来确保不会出现内存问题。

    我建议您不要逐节点创建.NET代码,而是为整个树/图结构创建一个.NET包装器,并提供一个.NET API,它可以将非托管API指针作为参数传递,但严格处理分配/解除分配,以避免出现内存问题。这将避免不必要地分配新的内存结构,只需分配已经存在的内容,即getParent函数。

        3
  •  0
  •   ironic    15 年前

    我有一个相关的问题。已显式删除非托管对象。所以我所做的是为所有包含静态字典的可用包装器实例的包装器创建一个基类。对象在构造函数中添加到字典,在wrapperBase.delete()方法中删除。注意,对于这种方法有显式的delete()方法是很重要的,否则GC将永远不会释放包装器实例,因为引用了静态字典。