Skip to content

Unable to use extension everything to write a generic Cast that works with LINQ query comprehensions #78415

@stephentoub

Description

@stephentoub

The LINQ specification expands:

from T t in source

to use source.Cast<T>().

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.

public static IAsyncEnumerable<TResult> Cast<TSource, TResult>(this IAsyncEnumerable<TSource> source)

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.

extension<TSource>(IAsyncEnumerable<TSource> source)
{
    public IAsyncEnumerable<TResult> Cast<TResult>() { ... }
}

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.

IAsyncEnumerable<Base> source = ...;
var result = source.Cast<Base, Derived>();

and the C# compiler refuses to use it to satisfy Cast.

IAsyncEnumerable<Derived> results1 = from x in source // OK
                                     select (Derived)x;

IAsyncEnumerable<Derived> results2 = from Derived x in source // Error!!
                                     select x;

cc: @jcouv, @MadsTorgersen

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions