I can get the following logic to work in 2 lines, but cannot pull it off inline:
var result = await BuildNewsCategories();
x.ListBuilder = () => result.Select(x => _mapper.Map<a, b>(x)).ToList();
My first attempt simply warns to add async:
x.ListBuilder = async () => await BuildNewsCategories()
.Select(x => _mapper.Map<a, b>(x)).ToList();
But this is where I get stuck as now .Select is not found.
CodePudding user response:
x.ListBuilder is a synchronous delegate, so you cannot change this to a one-liner.
Not without blocking anyway which should be avoided.
Even if you were to block, for example:
x.ListBuilder = () => BuildNewsCategories()
.Result
.Select(x => _mapper.Map<a, b>(x))
.ToList();
This would change the semantics of your code, because now BuildNewsCategories() is evaluated each time the delegate is invoked.
CodePudding user response:
TLDR: No, you cannot turn this into a usable one-liner since you have a synchronous delegate.
The rest of this answer provides extra information & potential solutions for other problems which may come up for when searching for this question.
Not having parentheses around await BuildNewsCategories() means that the compiler has no way of knowing:
- Are you trying to do
.Selecton theTask<TResult? Or: - Are you trying to do
.Selecton the result of theTask(TResult)?
Without parentheses, it thinks you're attempting to call the LINQ .Select extension method on the Task returned & not the actual returned result (the "unwrapped" awaited result).
To do .Select on the result of the Task, surround await BuildNewsCategories() in parentheses:
If x.ListBuilder is of type List<T>:
x.ListBuilder = (await BuildNewsCategories())
.Select(x => _mapper.Map<a, b>(x))
.ToList()
If x.ListBuilder is of type Func<Task<List<T>>>:
x.ListBuilder = async () => (await BuildNewsCategories())
.Select(x => _mapper.Map<a, b>(x))
.ToList();
If x.ListBuilder is of type Func<List<T>>, your delegate is synchronous & you won't be able to get a one-liner without blocking on asynchronous code (defeating the purpose).
Your original solution would be the answer in this case:
var result = await BuildNewsCategories();
x.ListBuilder = () => result
.Select(x => _mapper.Map<a, b>(x))
.ToList();
CodePudding user response:
The other answers get the issue with the parentheses right, but do not return a delegate, but a list.
So this would be the correct code:
x.ListBuilder = async () => (await BuildNewsCategories())
.Select(x => _mapper.Map<a, b>(x)).ToList();
This will work, if x.ListBuilder is of type Func<Task<List<b>>>, so it can be called as var list = await x.ListBuilder(). If it must be Func<List<b>>, it cannot be called asynchrounously and you have to move the await BuildNewsCategories() in a separate statement (your first snippet).
