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>();
} |
Beta Was this translation helpful? Give feedback.
-
How does that help the LINQ query comprehension? |
Beta Was this translation helpful? Give feedback.
-
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 😝 |
Beta Was this translation helpful? Give feedback.
-
Thanks, but if the pattern for |
Beta Was this translation helpful? Give feedback.
-
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) => ...;
} |
Beta Was this translation helpful? Give feedback.
-
I don't see |
Beta Was this translation helpful? Give feedback.
-
I wrote that extension, as a compromise. That shape doesn't work with sources that are of value types, unconstrained generics, etc. |
Beta Was this translation helpful? Give feedback.
-
I see. Please make your concerns heard in dotnet/csharplang#8696 where my alternate proposal would actually address this issue. |
Beta Was this translation helpful? Give feedback.
-
But doesn't suffer |
Beta Was this translation helpful? Give feedback.
-
No, it operates over the non-generic IEnumerable, and code like: |
Beta Was this translation helpful? Give feedback.
-
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 |
Beta Was this translation helpful? Give feedback.
-
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 |
Beta Was this translation helpful? Give feedback.
-
Please consider adding support for generic containing classes for extensions. |
Beta Was this translation helpful? Give feedback.
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
from
cast 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
Beta Was this translation helpful? Give feedback.
All reactions