Click here to Skip to main content
15,881,882 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi everyone!
Say i have two generic methods:

C#
int GetValue<T>() where T: unmanaged
{}

int GetAnotherValue<T>()
{}


I need to forward a call to one of those methods like this:

C#
void Init<T>()
{
    int i;
    //here is my problem
    if( T is unmanaged)
        i = GetValue<T>();
    else
        i = GetAnotherValue<T>();
}


I do not figure how to dispatch the call based on the generic type T.
Can someone help me?
Thanks.

What I have tried:

I do not know how to handle this problem
Posted
Updated 24-May-22 22:01pm
v2
Comments
PIEBALDconsult 24-May-22 16:46pm    
Maybe just use a try/catch ?

I think you need to provide more detailed code.
dzadel 24-May-22 17:01pm    
How to force the compiler to accept the call to the method with constraint?
dzadel 24-May-22 17:04pm    
here is a concret code:

static unsafe int SizeOf<T>() where T: unmanaged => sizeof(T);
static int GetSize<T>() => is T unmanaged ? SizeOf<T> : IntPtr.Size;

what construct to put in place of "is T unmanaged"?
PIEBALDconsult 24-May-22 17:21pm    
Have you looked into marshal.sizeof ?
https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshal.sizeof?view=net-6.0
dzadel 24-May-22 17:33pm    
This method do not accept generic type.
Take a look at its impl.

public static int SizeOf<t>()
{
Type t = typeof(T);
if (t.IsGenericType)
{
throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(T));
}

return SizeOfHelper(t, throwIfNotMarshalable: true);
}

1 solution

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:
C#
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[^]
 
Share this answer
 
Comments
PIEBALDconsult 25-May-22 12:32pm    
I think the OP still needs to explain the bigger picture of what he is trying to accomplish.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900