The first problem you'll have is that there doesn't seem to be any built-in way to identify an "unmanaged" type from your code. If you're using .NET Core 2.0 or later, you can use the
RuntimeHelpers.IsReferenceOrContainsReferences[
^] method, which is close; but there are still some edge cases it doesn't handle properly. The only way to be certain is to use
MakeGenericMethod
and catch the
ArgumentException
thrown if the type parameter doesn't satisfy the constraints.
The second problem is that you can't statically call a generic method with type constraints using a type parameter which does not have those constraints. If you try, you will get a
CS8377
compiler error. So you need to use reflection.
For example:
public class Foo
{
private static int GetUnmanagedValue<T>() where T : unmanaged
{
...
}
private static int GetManagedValue<T>()
{
...
}
private static readonly MethodInfo GetUnmanagedValueMethod = typeof(Foo).GetMethod(nameof(GetUnmanagedValue), BindingFlags.NonPublic | BindingFlags.Static);
private static int GetValue<T>()
{
try
{
var method = GetUnmanagedValueMethod.MakeGenericMethod(typeof(T));
return (int)method.Invoke(null, null);
}
catch (ArgumentException)
{
return GetManagedValue<T>();
}
}
private void Init<T>()
{
int i = GetValue<T>();
...
}
}
However, based on your comments, I don't think you've fully understood what an
unmanaged
type is. You can't assume that any type which doesn't satisfy the
unmanaged
constraint will be a reference type - it's quite possible to have a value type which doesn't satisfy that constraint.
Unmanaged generic type constraints - C# 7.3 draft specifications | Microsoft Docs[
^]