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

时间:2015-02-06 07:58:40

标签: c# .net generics

我有一个内部通用方法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);
   }
}

如果我只有UarrayOperation<U>(anything);相同),如何获取U以及如何使用T致电CustomMap<>?我见过的大多数问题都假设U已经知道了。序列化程序使用反射为每个具体类型构造单独的方法,然后缓存该方法。但在这里,我只想在我能够检测到这些情况时,将通用方法重定向/发送给特殊情况。

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

2 个答案:

答案 0 :(得分:5)

你的问题不是完全清楚,但听起来你基本上需要用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,则您遇到了麻烦 - 而您可能已经使用{{ 1}}尽管如此。在不知道你想要实现什么的情况下,我们无法判断这是否是一个问题。

答案 1 :(得分:1)

就像你能够阅读评论一样,泛型是不可能的。唯一的类型是T获取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的非通用版本。无论如何,大多数序列化(我是否正确理解,你序列化它?)与非泛型重载共享。