-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for async Select in LINQ #94
Comments
Isn’t it #70? |
@bahusoid sorry - wrong number. Fixed now. |
Maybe - it's indeed about delegate parameters. But it's not obvious to me - suggested examples and comments in issue are about method generations with parameters transformation. To support async selects it seems we don't need any of it (at least if suggested example now make sense) |
Though it seems my suggestion still not valid (as it simply blocks thread execution instead awaiting). It seems the valid conversion can't be written in LINQ. It should be: CriteriaLoader[] loaders = ...
var loadedLists = new List<IList>();
foreach (var l in loaders)
{
loadedLists.Add(await l.ListAsync(this, cancellationToken));
} Or am I wrong? Also I don't actually see how #70 can help here - could you please clarify? |
This feature is not related to #70 as the goal here is to convert the For supporting
The generator would need to known how to convert each method after the
Another example that we have to consider is when
Converting the above code to a
When an additional In short, supporting all scenarios would be very hard. Most likely I will initially add support for simpler cases and afterwards for complex ones. |
To make a sustainable solution we might want to add So this code: var result = loaders.Select(l => l.List(this)).Where(r => r.Count > 0).Select(r => r.First()).ToList(); With naive SelectAsync: public static async Task<IEnumerable<TResult>> SelectAsync<T, TResult>(
this IEnumerable<T> enumerable,
Func<T, Task<TResult>> selector)
{
//TODO: What about infinity IEnumerable`s?
var list = new List<TResult>();
foreach (var item in enumerable)
list.Add(await selector(item));
return list;
} Would become this: var result = (await loaders.SelectAsync(l => l.ListAsync(this)))
.Where(r => r.Count > 0)
.Select(r => r.First())
.ToList(); With SelectAsync with some IX magic: public static IAsyncEnumerable<TResult> SelectAsync<T, TResult>(
this IEnumerable<T> enumerable,
Func<T, Task<TResult>> selector)
{
return AsyncEnumerable.CreateEnumerable(() =>
{
var enumerator = enumerable.GetEnumerator();
var current = default(TResult);
return AsyncEnumerable.CreateEnumerator(async c =>
{
var moveNext = enumerator.MoveNext();
current = moveNext
? await selector(enumerator.Current).ConfigureAwait(false)
: default(TResult);
return moveNext;
},
() => current,
() => enumerator.Dispose());
});
} var result = loaders.SelectAsync(l => l.ListAsync(this))
.Where(r => r.Count > 0)
.Select(r => r.First())
.ToList(); |
After all, I think, that the best option would be to emit a warning/todo into the generated code saying that this code could potentially be converted to async, but without manual intervention this is not possible. |
Having a
The generator already does that, but there was a bug where it didn't worked for anonymous methods. I am currently not sure if it is a good idea to rewrite an |
Consider the following code in method that needs async counterpart:
I expect this part to be converted in to something like:
But current behavior keeps this LINQ expression as is.
The text was updated successfully, but these errors were encountered: