Here's a workaround. Instead of making the constraint on 'Delegate', you can make it on 'class' and then use a runtime cast to the generic type:
public TDelegate GetDelegate<TDelegate>(IntPtr p) where TDelegate : class
{
Delegate function = Marshal.GetDelegateForFunctionPointer(p, typeof(TDelegate));
// Ideally, we'd just make the constraint on TDelegate be
// System.Delegate, but compiler error CS0702 (constrained can't be System.Delegate)
// prevents that. So we make the constraint system.object and do the cast from object-->TDelegate.
object o = function;
return (TDelegate)o;
}
It's true there's still a runtime cast in there, but the cast has to be somewhere and at least the signature has a type-safe return value.