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
.Select
on theTask<TResult
? Or: - Are you trying to do
.Select
on 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" await
ed 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).