2012-03-30 11 views
17

Jestem nowy w LINQ. Muszę obliczyć zmiennej new_id następująco:LINQ "MaxOrDefault"?

public class C_Movement 
{ 
    public int id=-1; 
    public static ObservableCollection<C_Movement> list=new ObservableCollection<C_Movement>(); 
    // ... 
} 

int new_id = (C_Movement.list.Count==0) ? 0 : C_Movement.list.Max(x => x.id)+1; 

Czy istnieje sposób LINQ to kompaktowy, że ekspresja, tak, że nie trzeba używać? „:” Strukturę? Problem polega na tym, że gdy C_Movement.list nie zawiera żadnych elementów, C_Movement.list.Max (x => x.id) zwraca null (i chciałbym, aby zamiast tego zwrócił -1).

Dziękuję.

+2

Jak może zwrócić wartość null, gdy zwraca liczbę całkowitą? – MikeP

+1

Dla przyszłego odniesienia struktura "?:" Jest w rzeczywistości nazywana * operatorem warunkowym * (w dokumentach MSDN), ale większość ludzi nazywa to * operatorem potrójnym. * :) –

Odpowiedz

39

DefaultIfEmpty metoda powinna pomóc:

int new_id = C_Movement.list.Select(x => x.id).DefaultIfEmpty(-1).Max()+1; 
+2

Po angielsku: [DefaultIfEmpty] (http: // msdn.microsoft.com/en-us/library/bb355419.aspx) – Steve

+2

@Steve, dzięki. Edytowałem to, nie wahaj się, aby zmienić to następnym razem. – Snowbear

2

Jak o:

int new_id = 0; 

if (C_Movement.list.Any()) 
    new_id = C_Movement.list.Max(x => x.id) + 1; 
+2

Nie potrzebujesz "innego" tutaj, ponieważ już ustawiłeś to na '0' – hunter

+0

To prawda, myślę, że jestem analny o pewnych rzeczach. Złe nawyki umierają! –

+0

Głównym problemem związanym z tą wersją jest podwójne wyliczenie iteratora. "Any" będzie pierwszą iteracją, a "Max" będzie drugą. Tej implementacji należy unikać. – srm

3

int new_id = C_Movement.list.Max(x => (int?)x.id).GetValueOrDefault(-1) + 1;

gdzie GetValueOrDefault jest method z Nullable<T>.

+3

Warto zauważyć, że tylko Max() na kolekcjach typów zerowujących zwraca null dla pustej sekwencji, podczas gdy Max() generalnie zgłasza wyjątek. – sluki