我創建的類型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
或重寫「終結」的方法,如果IntPtr<T>
類型的這種變量超出破壞發生的範圍,但GCHandle
將不會免費。
UPDATE
由於這類用途的例子,假設我們打算從COM
interpo 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
?
只是...爲什麼?你在這裏試圖做什麼?既然你已經限制了'T:struct',你已經有了基於範圍的生命週期...?或者如果它*是一個類,那麼假設(從這裏的用法來看)它是短暫的,它將被收集在第0代*反正*中,這是非常便宜的。 –
嗯...這個班應該是類似於IntPtr的類型嗎? IntPtr不會跟蹤生命週期,它只是一個像C指針一樣的指針。 – Skurmedel
參見上面的示例 –