简体   繁体   English

如何使用泛型的基本泛型类型C#

[英]How to use underlying generic types of generics C#

I have an internal generic method byte[] catchAllOperation<T>(T genericItem) and another one byte[] arrayOperation<T>(T[] genericArray) . 我有一个内部的通用方法byte[] catchAllOperation<T>(T genericItem)和另一个byte[] arrayOperation<T>(T[] genericArray) Additionally, I have a highly specialized operation byte[] specializedOperation<TKey,TValue>(CustomMap<Tkey,TValue> customMap) . 另外,我有一个高度专门的操作byte[] specializedOperation<TKey,TValue>(CustomMap<Tkey,TValue> customMap)

How to write a method like this? 如何编写这样的方法? (pseudocode): (伪代码):

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);
   }
}

How to get U and how to call arrayOperation<U>(anything); 如何获取U以及如何调用arrayOperation<U>(anything); with U if I have only T (and the same for CustomMap<> )? 如果我只有T (与CustomMap<>相同),则与U使用? Most questions I have seen assume that U is already known. 我见过的大多数问题都假定U已为人所知。 Serializers use reflection to construct a separate method for each concrete type and then cache the method. 序列化器使用反射为每种具体类型构造一个单独的方法,然后对该方法进行缓存。 But here I only want to redirect/dispatch a universal method to special cases when I could detect these cases. 但是在这里,我只想在可以检测到特殊情况时将通用方法重定向/调度到特殊情况。

I will have more types similar to CustomMap , so there is time to make any radical changes to code/approach. 我将有更多类似于CustomMap类型,因此有时间对代码/方法进行任何根本性的更改。 All special methods leverage the fact that for blittable underlying types some transformations and custom layout significantly boost the compression ratio of custom types. 所有特殊方法都利用了这样的事实,即对于可绑定基础类型,某些转换和自定义布局会大大提高自定义类型的压缩率。 For custom types I could implement an interface, but for generic arrays it is not an option. 对于自定义类型,我可以实现一个接口,但是对于通用数组,则不是一个选择。

Your question isn't entirely clear to me, but it sounds like you basically need to look in typeof(T) with reflection. 您的问题对我来说并不完全清楚,但是听起来您基本上需要使用反射来查看typeof(T) Fortunately, dynamic typing in C# means you can get the compiler team to do the hard work - admittedly at execution time: 幸运的是,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
}

Note that your UniversalOperation method doesn't have to be generic now - it will just use the execution-time type of the value. 请注意,您的UniversalOperation方法现在不必是通用的-它只会使用值的执行时类型。 Of course, that means it may not be quite as you originally intended - for example, if the value is null , you're in trouble - whereas you could have potentially worked with typeof(T) despite that. 当然,这意味着它可能不能原来打算-例如,如果该值为null ,你就麻烦了-而你可能会潜在合作过typeof(T)尽管这一点。 Without knowing what you're trying to achieve, we can't tell whether or not that's a problem. 不知道您要实现什么目标,我们就无法确定这是否是一个问题。

Like you are able to read comments it is not possible with generics. 就像您能够阅读注释一样,泛型是不可能的。 The only type is T do getting U and other types is not possible without reflection. 唯一的类型是T确实可以得到U而其他类型则必须经过反射才能实现。 Sample solution: 样品溶液:

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);
    }
}

Unfortunately, solution above required non-generic version of specializedOperation . 不幸的是,解决上述要求的非通用版本specializedOperation Anyway, most of serializes (did I understand corretly, you serialize it?) share with non-generic overloads. 无论如何,大多数序列化(我正确理解了,您序列化了吗?)与非泛型重载共享。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM