Recommended way to bridge generic constraints #106275
-
What is the recommended way to bridge generic constraints? For example, say I have a generic I've seen in the runtime usage of public static T SomeLogic<T>(T input, out T output)
where T : IFloatingPoint<T>
{
if (typeof(T) == typeof(float))
{
T result = (T)(object)SomeLogic_Ieee754((float)(object)input, out float outputTemp);
output = (T)(object)outputTemp;
return result;
}
if (typeof(T) == typeof(double))
{
T result = (T)(object)SomeLogic_Ieee754((double)(object)input, out double outputTemp);
output = (T)(object)outputTemp;
return result;
}
return SomeLogic_NotIeee754(input, out output);
}
private static T SomeLogic_NotIeee754<T>(T input, out T output)
where T : IFloatingPoint<T>
{ /* ... */ }
private static T SomeLogic_Ieee754<T>(T input, out T output)
where T : IFloatingPointIeee754<T>
{ /* ... */ } Alternatively, is public static T SomeLogic<T>(T input, out T output)
where T : struct, IFloatingPoint<T>
{
if (typeof(T) == typeof(float))
{
T result = Unsafe.BitCast<float, T>(SomeLogic_Ieee754(Unsafe.BitCast<T, float>(input), out float outputTemp);
output = Unsafe.As<float, T>(outputTemp);
return result;
}
if (typeof(T) == typeof(double))
{
T result = Unsafe.BitCast<double, T>(SomeLogic_Ieee754(Unsafe.BitCast<T, double>(input), out double outputTemp);
output = Unsafe.As<double, T>(outputTemp);
return result;
}
return SomeLogic_NotIeee754(input, out output);
} |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 7 replies
-
Depending on the use case, in lieu of absence of "bridging generic constraints in C#" feature, you can get the necessary codegen today with the following: static void OpenGenericMethod<T>(T value) {
if (value is IFastPathFeature) {
((IFastPathFeature)value).FastPathMethod();
}
Fallback();
} Assuming |
Beta Was this translation helpful? Give feedback.
If you've done a
if (typeof(T) == typeof(...))
typecheck, then(T)(object)value
is the more common pattern.Unsafe.BitCast<double, T>
should also work fine on any version of RyuJIT and the version of Mono shipping alongside .NET 9. Older versions of Mono didn't handle it well (and may not handle(T)(object)value
well either, as they tend to not do generic specialization in the same way RyuJIT does).If you've not done a
if (typeof(T) == typeof(...))
check, then its not safe. So this pattern only works for a concrete set ofT
you've opted to support and that can be problematic, since you can miss cases. The original sample code would not be handlingHalf
for example or the existingNFloat
,…