结构和析构函数

本文关键字:析构函数 结构 | 更新日期: 2023-09-27 18:06:21

我创建了类型IntPtr<T>作为c/c++具有的通用指针:

public struct IntPtr<T> : IDisposable where T : struct
{
    private static Dictionary<IntPtr, GCHandle> handles = new Dictionary<IntPtr, GCHandle>();
    private IntPtr ptr;
    public IntPtr(ref T value)
    {
        GCHandle gc = GCHandle.Alloc(value, GCHandleType.Pinned);
        ptr = gc.AddrOfPinnedObject();
        handles.Add(ptr, gc);
    }
    public IntPtr(ref T[] value)
    {
        GCHandle gc = GCHandle.Alloc(value, GCHandleType.Pinned);
        ptr = gc.AddrOfPinnedObject();
        handles.Add(ptr, gc);
    }
    public IntPtr(IntPtr value)
    { ptr = value; }
    public IntPtr(IntPtr<T> value)
    { ptr = value.ptr; }
    public void Dispose()
    {
        if (handles.ContainsKey(ptr))
        {
            GCHandle gc = handles[ptr];
            gc.Free();
            handles.Remove(ptr);
            ptr = IntPtr.Zero;
        }
    }
    public T? this[int index]
    {
        get
        {
            if (ptr == IntPtr.Zero) return null;
            if (index < 0) throw new IndexOutOfRangeException();
            if (handles.ContainsKey(ptr))
            {
                GCHandle gc = handles[ptr];
                if (gc.Target is Array) return ((T[])gc.Target)[index];
                return (T)gc.Target;
            }
            return null;
        }
        set
        {
            if (index < 0) throw new IndexOutOfRangeException();
            // not yet implemented
        }
    }
    private T[] getArray()
    {
        if (handles.ContainsKey(ptr)) return (T[])handles[ptr].Target;
        return null;
    }
    public int Count
    {
        get
        {
            if(handles.ContainsKey(ptr))
            {
                GCHandle gc = handles[ptr];
                if (gc.Target is Array) return ((T[])gc.Target).Length;
                return 1;
            }
            return 0;
        }
    }
    public static implicit operator IntPtr(IntPtr<T> value) { return value.ptr; }
    public static implicit operator T(IntPtr<T> value) { return (T)value[0]; }
    public static implicit operator T[](IntPtr<T> value) { return value.getArray(); ; }
    public static implicit operator T?(IntPtr<T> value) { return value[0]; }
}

它还没有完成,但现在它的工作,问题是我保持跟踪GCHandle通过存储它们在handles现在我需要释放GCHandle一旦它不再需要,所以我必须声明一个destrcutor,但c#不允许structdestrcutor或覆盖'Finalize'方法,如果类型IntPtr<T>这样的变量超出范围的破坏发生,但GCHandle不会自由。

作为这个类使用的一个例子,假设我们要从COM中插入COAUTHIDENTITYCOAUTHINFO,它看起来像这样:

[StructLayout(LayoutKind.Sequential)]
struct COAUTHIDENTITY
{
    [MarshalAs(UnmanagedType.LPWStr)] string User;
    uint UserLength;
    [MarshalAs(UnmanagedType.LPWStr)] string Domain;
    uint DomainLength;
    [MarshalAs(UnmanagedType.LPWStr)] string Password;
    uint PasswordLength;
    uint Flags;
}
[StructLayout(LayoutKind.Sequential)]
struct COAUTHINFO
{
    uint dwAuthnSvc;
    uint dwAuthzSvc;
    [MarshalAs(UnmanagedType.LPWStr)] string pwszServerPrincName;
    uint dwAuthnLevel;
    uint dwImpersonationLevel;
    IntPtr<COAUTHIDENTITY> pAuthIdentityData;
    uint dwCapabilities;
}

pAuthIdentityDataIntPtr替换为Marshal成员函数来获取类型为COAUTHIDENTITY的对象,IntPtr<T>将使其更简单。

问题是:当IntPtr<T>被释放时,我应该在哪里写代码来释放GCHandle ?

结构和析构函数

你在重新发明轮子。看看SafeHandle类。使用现有的后代或创建您自己的后代。