如何使用泛型的底层泛型类型 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);
}
}
如果我只有 T
(CustomMap<>
也是如此),如何获得 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
的非通用版本。无论如何,大多数序列化(我理解正确吗,你序列化了它?)与非泛型重载共享。
我有一个内部泛型方法 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);
}
}
如果我只有 T
(CustomMap<>
也是如此),如何获得 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
的非通用版本。无论如何,大多数序列化(我理解正确吗,你序列化了它?)与非泛型重载共享。