Click here to Skip to main content
15,354,930 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);
}
PIEBALDconsult 24-May-22 17:38pm
   
Well, you should improve the question to indicate exactly _what_ you are trying to accomplish and less on _how_ you think you need to do it.
dzadel 24-May-22 17:49pm
   
I need to allocate a buffer based on a generic type T. if T is managed then the size of each item is the size of a refernce, otherwise T is a struct and a have to call my SizeOf<t>() method and get the size of this struct.

I nedd, for example implementing a method like:
static byte[] AllocBuffer<T>(int itemCount)
{}
Jon McKee 24-May-22 20:09pm
   
You'll probably have to check these properties (or whatever ones you're interested in) manually: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/unmanaged-types

There's no easy property I'm aware of via the Type or TypeInfo classes like an isUnmanaged property, but those classes do have all the information listed in the link above, so you could make your own.
dzadel 25-May-22 4:39am
   
Ok Thanks for your help.

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[^]
   
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