如何使用泛型的底层泛型类型 C#

How to use underlying generic types of generics C#

我有一个内部泛型方法 byte[] catchAllOperation<T>(T genericItem) 和另一个 byte[] arrayOperation<T>(T[] genericArray)。此外,我有一个高度专业化的操作 byte[] specializedOperation<TKey,TValue>(CustomMap<Tkey,TValue> customMap).

这样的方法怎么写? (伪代码):

public byte[] universalOperation<T>(T anything){
   if(T is CustomMap<UKey,UValue>){      // UKey/UValue are unknown
       return specializedOperation<UKey,UValue>(anything);
   } else if(T is U[]){                    // U is unknown
       return arrayOperation<U>(anything);
   }else{
       return catchAllOperation<T>(anything);
   }
}

如果我只有 TCustomMap<> 也是如此),如何获得 U 以及如何用 U 调用 arrayOperation<U>(anything);?我见过的大多数问题都假设 U 是已知的。序列化程序使用反射为每个具体类型构造一个单独的方法,然后缓存该方法。但在这里我只想 redirect/dispatch 一个通用的方法来处理特殊情况,当我可以检测到这些情况时。

我将有更多类似于 CustomMap 的类型,因此有时间对 code/approach 进行任何彻底的更改。所有特殊方法都利用了这样一个事实,即对于可 blittable 底层类型,一些转换和自定义布局显着提高了自定义类型的压缩率。对于自定义类型,我可以实现一个接口,但对于泛型数组,它不是一个选项。

完全 不清楚你的问题,但听起来你基本上需要 typeof(T) 反思一下。幸运的是,C# 中的动态类型意味着您可以让编译器团队完成艰苦的工作——诚然在执行时:

// Note: all names changed to be more conventional
public byte[] UniversalOperation<T>(T value)
{
    dynamic d = value;
    return DynamicOperation(d);
}

private byte[] DynamicOperation<UKey, UValue>(CustomMap<UKey, UValue> map)
{
    // Do stuff with the map here
}

private byte[] DynamicOperation<U>(U[] array)
{
    // Do something with the array here
}

private byte[] DynamicOperation(object value)
{
    // Fallback
}

请注意,您的 UniversalOperation 方法现在不必是通用的 - 它只会使用值的执行时类型。当然,这意味着它可能不像您最初预期的那样相当——例如,如果值为null,你就有麻烦了——而你可能已经工作了typeof(T) 尽管如此。在不知道您要实现的目标的情况下,我们无法判断这是否是一个问题。

就像你能够阅读评论一样,泛型是不可能的。唯一的类型是 T do getting U 并且其他类型没有反射是不可能的。 示例解决方案:

public static void UniversalOperation<T>(T anything)
{
    // check for null etc.
    var anythingType = anything.GetType();

    if (anythingType.IsGenericType &&
          anythingType.GetGenericTypeDefinition() == typeof(CustomMap<,>))
    {
        var genericArgs = anythingType.GetGenericArguments();
        var keyType = genericArgs[0];
        var valueType = genericArgs[1];

        return specializedOperation(keyValue, valueType, anything);
    }
    else if (anythingType.IsArray)
    {
        var elemType = anythingType.GetElementType();
        return arrayOperation(elemType, anything);
    }
    else
    {
        //T is parameter, so you can pass it
        catchAllOperation<T>(anything);
    }
}

不幸的是,上述解决方案需要 specializedOperation 的非通用版本。无论如何,大多数序列化(我理解正确吗,你序列化了它?)与非泛型重载共享。