Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Disposable pinned GCHandle
using System;
using System.Runtime.InteropServices;
namespace IISResetMe.SafeHandles
/// <summary>Disposable pinned memory handles, useful for non-blittable type references passed to unmanaged code</summary>
public class GCPinnedHandle : IDisposable
private GCHandle gcHandle;
/// <summary>Allocates a pinned handle for <see cref="target">the target</see> object</summary>
/// <param name="target">The target object for which pinning is required</param>
public GCPinnedHandle(object target)
if (target == null)
throw new ArgumentException("Invalid target", new NullReferenceException());
gcHandle = GCHandle.Alloc(target, GCHandleType.Pinned);
/// <summary>Used to free the allocated handle</summary>
public void Dispose()
if (gcHandle.IsAllocated)
/// <summary>Implicit conversion to IntPtr</summary>
public static implicit operator IntPtr(GCPinnedHandle pinnedHandle)
if (!pinnedHandle.gcHandle.IsAllocated)
throw new InvalidCastException("An attempt was made to obtain a pointer to unallocated memory during conversion");
return pinnedHandle.gcHandle.AddrOfPinnedObject();

This comment has been minimized.

Copy link
Owner Author

commented Mar 12, 2019


/// ...
static extern IntPtr DoStuff([In] IntPtr arrayOfThings);

static extern IntPtr CheckBackOnStuff(IntPtr refHandle);

// ...

var myArray = new NonBlittableType[length];
var results = new NonBlittableType[length];

using(pinnedHandle = new GCPinnedHandle(myArray))
  var refHandle = DoStuff(pinnedHandle);
  // ... more stuff happening
  var refToModifiedThings = CheckBackOnStuff(refHandle);
  Marshal.Copy(refToModifiedThings, results, 0, length);
// pinned handle automatically freed now, no worries
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.