结构和析构函数
本文关键字:析构函数 结构 | 更新日期: 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#不允许struct
有destrcutor
或覆盖'Finalize'方法,如果类型IntPtr<T>
这样的变量超出范围的破坏发生,但GCHandle
不会自由。
作为这个类使用的一个例子,假设我们要从COM
中插入COAUTHIDENTITY
和COAUTHINFO
,它看起来像这样:
[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;
}
将pAuthIdentityData
和IntPtr
替换为Marshal
成员函数来获取类型为COAUTHIDENTITY
的对象,IntPtr<T>
将使其更简单。
问题是:当IntPtr<T>
被释放时,我应该在哪里写代码来释放GCHandle
?
你在重新发明轮子。看看SafeHandle类。使用现有的后代或创建您自己的后代。