Repository navigation
Unable to use extension everything to write a generic Cast that works with LINQ query comprehensions #78730
Replies: 13 comments
|
@stephentoub would breaking the method down into 2 components help here? public static AsyncEnumerableCaster<TResult> Cast<TSource>(this IAsyncEnumerable<TSource> source)public class AsyncEnumerableCaster
{
public IAsyncEnumerable<TResult> To<TResult>();
}Obviously it's not ideal since the call pattern then becomes different than the original I've used this trick many times to overcome the lack of partial generic type inference in C#. A common example for us: public TTarget Map<TSource, TTarget>(TSource source);Becomes: public Mapping<TSource> Map<TSource>(TSource source);public class Mapping<TSource>
{
TTarget To<TTarget>();
} |
|
How does that help the LINQ query comprehension? |
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 Otherwise just ignore the idea π |
|
Thanks, but if the pattern for |
|
Maybe introducing discards for generic arguments could solve this? extension(IEnumerable<_>)
{
// 1-phase lookup, for compat, generic argument in the method declaration
public static IEnumerable<T> M<T>(out T t) => ...;
}
extension<T>(IEnumerable<T>)
{
// 2-phase lookup, generic argument in the extension declaration
public static IEnumerable<T> M(out T t) => ...;
} |
|
I don't see |
I wrote that extension, as a compromise. That shape doesn't work with sources that are of value types, unconstrained generics, etc. |
I see. Please make your concerns heard in dotnet/csharplang#8696 where my alternate proposal would actually address this issue. |
But doesn't suffer |
No, it operates over the non-generic IEnumerable, and code like: |
|
But what, if one writes: IEnumerable<int> e = [1, 2, 3];
var result = from long i in e
select i;That would not work - as with any value type (even if there are user defined conversions) - because of the boxing performed under the hood... And isn't the idea of having a BTW: how would a fully generic version of |
|
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 |
Please consider adding support for generic containing classes for extensions. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
The LINQ specification expands:
to use
source.Cast<T>().For
Enumerable.Cast<T>, this works because the source is a non-genericIEnumerable, 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.and the C# compiler refuses to bind the
fromcast syntax when the arity of Cast doesn't match.I was expecting extension everything would fix this, 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.
and the C# compiler refuses to use it to satisfy Cast.
cc: @jcouv, @MadsTorgersen
All reactions