I'm trying to use LINQ:
IEnumerable<String> debtors = (from expense in开发者_StackOverflow社区 CurrentExpenses
where expense.WhoPaid == username
select expense.WhoOwes.AsEnumerable()).Distinct();
(username
and WhoPaid
are strings, WhoOwes
is ICollection<String>
)
What I want to do is get an IEnumerable
of, for each expense
where username
paid, all the people who owe for it. I'm not really sure how to do it. Here is the compiler error:
Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<System.Collections.Generic.IEnumerable<string>>' to 'System.Collections.Generic.IEnumerable<string>'. An explicit conversion exists (are you missing a cast?)
What is the correct syntax for this?
The code you've provided doesn't compile because you're trying to assign a sequence of a sequence of strings (each top-level sequence coming from a specific expense) to a reference that expects a sequence of strings.
Going by the return-type of your query, I assume you only need a sequence containing all the debtors for the user? If so, you need to flatten the result sequence.
// implicitly IEnumerable<string>
var debtors = CurrentExpenses.Where(expense => expense.WhoPaid == username)
.Select(expense => expense.WhoOwes)
.SelectMany(debtors => debtors) // flatten sequence
.Distinct();
(you can use a single SelectMany
clause to do the projection and flattening together.)
or, in query syntax:
var debtors = (from expense in CurrentExpenses
where expense.WhoPaid == username
from debtor in expense.WhoOwes
select debtor).Distinct();
If you need to find all expenses paid by the user and their associated debtors, you can stop at the first filter:
// implicitly IEnumerable<Expense>
var expensesPaidByUser = CurrentExpenses.Where(expense => expense.WhoPaid == username);
The debtors associated with each expense are already encapsulated in theExpense
object, so you probably don't need a query more complicated than this; it's already effectively a sequence of a sequence of debtors grouped by expense.
If you do want a separate type to hold an expense and its associated debtors, you can do this with an anonymous type, although I don't see why its necessary in your case:
// implictly IEnumerable<anonymousType>
var debtorsByExpense = CurrentExpenses.Where(expense => expense.WhoPaid == username)
.Select(expense => new { Expense = expense, Debtors = expense.WhoOwes });
Use:
var debtors = ...
instead of
IEnumerable<String> debtors = ...
The return type of LINQ expressions is often difficult to determine for the programmer. The var
keyword tells the compiler to infer the type automatically, so you don't need to. Hover your mouse cursor over var
in your IDE to see what the compiler has inferred.
精彩评论