Repository navigation
Downcast of generic types #136323
Replies: 2 comments
|
The pattern fails at compile time: C# has to be able to construct For your return-only parser, a JIT workaround is to keep Add this inside public static T Parse<T>() where T : INumber<T> => Parser<T>.Run();
private static class Parser<T> where T : INumber<T>
{
internal static readonly Func<T> Run = Create();
private static Func<T> Create()
{
Type t = typeof(T);
bool Has(Type definition) => t.GetInterfaces().Any(i =>
i.IsGenericType && i.GetGenericTypeDefinition() == definition &&
i.GenericTypeArguments[0] == t);
string name = Has(typeof(IBinaryInteger<>)) ? nameof(Parse_Int)
: Has(typeof(IFloatingPoint<>)) ? nameof(Parse_Float)
: throw new NotSupportedException($"No parser for {t}.");
return (Func<T>)typeof(Assistant)
.GetMethod(name, BindingFlags.Public | BindingFlags.Static)!
.MakeGenericMethod(t)
.CreateDelegate(typeof(Func<T>));
}
}
I compiled the original pattern and got CS0314 for both interfaces. The dispatcher passed checks with This is not automatically trimming/NativeAOT-safe: Also, the NaN/infinity check alone does not require a floating-point constraint: For the language enhancement in your last question, the constraint-bridging proposal, linked in Xiao's reply, describes allowing a checked branch to satisfy a stronger generic constraint. The dispatcher above provides a workaround on .NET 10. |
|
This is a common problem, and have been widely discussed in #6308. However,I don't know when runtime will support this feature |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Generic math has given us a ton of functionality to write clean and elegant code that required a bunch of ugly workarounds before.
However, it's difficult (or impossible?) to write a generic method that takes an
INumber<T>and casts it to a derived interface likeIBinaryInteger<T>orIFloatingPoint<T>and continue on different paths based on the actual type.This works, but is useless, because the generic types must be specified in the call:
This would be useful, but does not compile, because
INumber<T>cannot be casted toIBinaryInteger<T>because theTofINumber<T>does not implementIBinaryInteger<T>:It isn't possible either to write 2 methods that only differ in the used generic type constraint (this seems to be #129350):
So, what workarounds exist to solve this problem?
Could a new functionality or enhancement in the runtime solve it?
My usage scenario actually is a little different, it would require even more enhancements or further workarounds, because I don't have a function with generic typed arguments, but with generic return values only:
All reactions