You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Unable to use extension everything to write a generic Cast that works with LINQ query comprehensionsΒ #78415
For Enumerable.Cast<T>, this works because the source is a non-generic IEnumerable, and thus there's only the one generic type parameter for the result.
For AsyncEnumerable.Cast, this falls down. Such a Cast extension method today needs to be generic on both the TSource and TResult, e.g.
but unfortunately it doesn't. While I can write the above, it doesn't provide any expressive power that didn't already exist with extension methods today, because the resulting method still has a generic arity of 2, and I still need to provide both type arguments in order to use it, e.g.
changed the title [-]Unable to use extension everything to write a generic Cast that works with LINQ[/-][+]Unable to use extension everything to write a generic Cast that works with LINQ query comprehensions[/+]on May 2, 2025
Well it was more of a question as to whether it could help or not. If the issue was the lack of partial inference, and an additional mapping could be added for Cast().To<T>() instead of just Cast<T>() in the pattern recognized by from T t in source that could work.
Maybe introducing discards for generic arguments could solve this?
extension(IEnumerable<_>){// 1-phase lookup, for compat, generic argument in the method declarationpublicstaticIEnumerable<T>M<T>(outTt)=>...;}extension<T>(IEnumerable<T>){// 2-phase lookup, generic argument in the extension declarationpublicstatic IEnumerable<T> M(outTt)=>...;}
That would not work - as with any value type - because of the boxing performed under the hood...
And isn't the idea of having a Cast<T> operator exactly that - converting the element to the desired type (note, that (long)i is possible). With reference types one can cast to arbitrary target types (as long as there is a conversion).
BTW: how would a fully generic version of Cast<T,TResult> look like - I seem to miss something with the generics...
From offline and LDM discussion, the is by-design. The extensions everything feature does not make this better or worse. We would likely need a proposal for LINQ to solve this. I'll move to csharplang
From offline and LDM discussion, the is by-design. The extensions everything feature does not make this better or worse. We would likely need a proposal for LINQ to solve this. I'll move to csharplang
Please consider adding support for generic containing classes for extensions.
Activity
[-]Unable to use extension everything to write a generic Cast that works with LINQ[/-][+]Unable to use extension everything to write a generic Cast that works with LINQ query comprehensions[/+]julealgon commentedon May 2, 2025
@stephentoub would breaking the method down into 2 components help here?
Obviously it's not ideal since the call pattern then becomes different than the original
IEnumerableone.I've used this trick many times to overcome the lack of partial generic type inference in C#. A common example for us:
Becomes:
stephentoub commentedon May 2, 2025
How does that help the LINQ query comprehension?
julealgon commentedon May 2, 2025
Well it was more of a question as to whether it could help or not. If the issue was the lack of partial inference, and an additional mapping could be added for
Cast().To<T>()instead of justCast<T>()in the pattern recognized byfrom T t in sourcethat could work.Otherwise just ignore the idea π
stephentoub commentedon May 2, 2025
Thanks, but if the pattern for
from T t in sourceis going to be modified, it could also be modified to recognize the two-generic-parameter signature.aromaa commentedon May 6, 2025
Maybe introducing discards for generic arguments could solve this?
Blaisor commentedon May 24, 2025
I don't see
TSourcein the official implementation: AsyncEnumerable.Cast(IAsyncEnumerable)Wouldn't this extension method work for you?
stephentoub commentedon May 24, 2025
I wrote that extension, as a compromise. That shape doesn't work with sources that are of value types, unconstrained generics, etc.
Blaisor commentedon May 24, 2025
I see. Please make your concerns heard in dotnet/csharplang#8696 where my alternate proposal would actually address this issue.
martin-steinhoefer commentedon May 26, 2025
But doesn't suffer
Enumerable.Cast<T>from a very similar problem?stephentoub commentedon May 26, 2025
No, it operates over the non-generic IEnumerable, and code like:
https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA+ABADAAgwRhQG4BYAKGz3wDoAZASwDsBHUs8ggZgB4mAXAHw4YOALw4A2vgA0OAEyzOAXTbkAbgEMoOWAGcArgBs+YnADMoEALY5+t242HkcL129e6YhmGBP0iQA===
works fine.
martin-steinhoefer commentedon May 26, 2025
But what, if one writes:
That would not work - as with any value type - because of the boxing performed under the hood...
And isn't the idea of having a
Cast<T>operator exactly that - converting the element to the desired type (note, that(long)iis possible). With reference types one can cast to arbitrary target types (as long as there is a conversion).BTW: how would a fully generic version of
Cast<T,TResult>look like - I seem to miss something with the generics...jcouv commentedon May 28, 2025
From offline and LDM discussion, the is by-design. The extensions everything feature does not make this better or worse. We would likely need a proposal for LINQ to solve this. I'll move to csharplang
Blaisor commentedon May 28, 2025
Please consider adding support for generic containing classes for extensions.