You're overthinking the problem. Let's break it down into two steps. First, group the contacts by number:
var q1 = from c in contacts
group c by c.PersonalNumber;
OK, we now have a sequence of groups, where each group is a sequence of contacts that have the same number.
Now, we want the groups that have a single contact in the sequence, and we want that contact:
var q2 = from g in q1
where g.Count() == 1
select g.First();
Alternatively, we could use a select-many to extract the single contact from the list:
var q2 = from g in q1
where g.Count() == 1
from c in g
select c;
And we're done; we could stop here. If we wanted though, how could we make this into one query?
We notice that we are feeding q1 into q2, so we could combine them like this:
var q = from g in (
from c in contacts
group c by c.PersonalNumber)
where g.Count() == 1
select g.First();
But this is actually harder to read. In this situation it is better to use a query continuation with into
:
var q = from c in contacts
group c by c.PersonalNumber into g
where g.Count() == 1
select g.First();
Or, using a select-many:
var q = from c in contacts
group c by c.PersonalNumber into g
where g.Count() == 1
from c in g
select c;
And we're done; we've got a sequence of contacts where each contact's number appears exactly once.
The benefit of a query continuation is that every operation runs in the same order that it appears on the page:
- We start with the contacts
- We group them
- We filter the groups
- We extract the contacts from the remaining groups
That's what you want in a LINQ query: you want the order of the items in the query to match the logical order of the operations that happen to the collection of data.
Note that my last "comprehension" format solution here is logically exactly the same as the "fluent" form in Anu Viswam's answer. My preference is to use the comprehension syntax when it is convenient to do so, but many people prefer the fluent form; choose whichever one makes most sense to you.