I have an internal generic method byte[] catchAllOperation<T>(T genericItem)
and another one byte[] arrayOperation<T>(T[] genericArray)
. Additionally, I have a highly specialized operation 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);
with U
if I have only T
(and the same for CustomMap<>
)? Most questions I have seen assume that U
is already known. 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. 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. Fortunately, dynamic typing in C# means you can get the compiler team to do the hard work - admittedly at execution time:
// 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. 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. Without knowing what you're trying to achieve, we can't tell whether or not that's a problem.
See more on this question at Stackoverflow