我有一个内部通用方法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);
}
}
如果我只有U
(arrayOperation<U>(anything);
相同),如何获取U
以及如何使用T
致电CustomMap<>
?我见过的大多数问题都假设U
已经知道了。序列化程序使用反射为每个具体类型构造单独的方法,然后缓存该方法。但在这里,我只想在我能够检测到这些情况时,将通用方法重定向/发送给特殊情况。
我将有更多类似于CustomMap
的类型,因此有时间对代码/方法进行任何根本性的更改。所有特殊方法都利用了这样一个事实:对于blittable底层类型,一些转换和自定义布局显着提高了自定义类型的压缩率。对于自定义类型,我可以实现一个接口,但对于通用数组,它不是一个选项。
答案 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
的非通用版本。无论如何,大多数序列化(我是否正确理解,你序列化它?)与非泛型重载共享。