2016-01-22 11 views
5

In questo momento il mio codice simile a questo:Iniziatore della raccolta C#: è possibile aggiungere un elemento facoltativamente, in base a una condizione?

var ids = projectId.HasValue ? new List<Guid> { projectId.Value } : new List<Guid>(); 

Esiste un modo più succinta di creazione di una lista in una sola riga di codice, con un elemento aggiunto opzionalmente?

+0

Forse dovresti considerare di avvolgere l'Elenco e sovraccaricare il metodo Add (T) con condizioni interne. – MaLiN2223

+7

In una singola affermazione è probabilmente la migliore che puoi fare. Se lo fai molto potresti aggiungere un metodo di estensione per creare collezioni da nullables. – Lee

+0

@Live un metodo di estensione non sembra una cattiva idea, in realtà. –

risposta

1

Questo probabilmente non è una buona idea, ma in C# 6, collection initializers also work when Add() is an extension method .

Questo significa che è possibile scrivere l'estensione Add() in questo modo:

public static void Add<T>(this List<T> list, T? item) where T : struct 
{ 
    if (item.HasValue) 
    { 
     list.Add(item.Value); 
    } 
} 

E poi questo codice farà ciò che si vuole:

var list = new List<Guid> { projectId }; 

Si noti che questo funziona solo per i tipi di valore (perché della distinzione T/T?) e non esiste un modo semplice per farlo funzionare per i tipi di riferimento.

Inoltre, troverei la riga sopra molto sorprendente, essendo più succinta non è sempre migliore. Questo è il motivo per cui in realtà non utilizzerei questo codice.

+0

Grazie! E ora che ci ho pensato, hai ragione in quanto più breve non è sempre meglio. –

+0

Se qualcuno che ha scritto ha lavorato nella mia azienda, li picchiavo a morte con la loro pinzatrice. –

+0

@JoeEnos Dire che non è un buon doppio non è abbastanza buono per te? :-) – svick

1

che è piuttosto succinta, ma un'altra opzione sarebbe quella di utilizzare LINQ:

var ids = new[] { projectId }.Where(x => x.HasValue).Select(x => x.Value).ToList(); 
+4

È quasi della stessa lunghezza e nasconde l'intenzione del codice. –

+0

@YacoubMassad Ogni byte conta, giusto?:) –

+0

Hai salvato forse 2 caratteri, ma se sto leggendo questo codice in un progetto, penserei che ci siano alcune query complesse in corso. Non capirei l'intenzione originale. –

2

vorrei risolvere questo utilizzando un metodo di estensione come questo:

public static void AddIfNotNull<T>(this List<T> list, T? value) where T : struct 
{ 
    if(value != null) 
    { 
     list.Add(value.Value); 
    } 
} 

di quello che potrebbe essere utilizzato in questo modo:

var ids = new List<Guid>(); 
ids.AddIfNotNull(projectId); 

Forse non come "furbo" (e non un one-liner) come vostra proposta, ma a mio avviso è molto più facile da leggere e capire. Se si desidera utilizzarlo come one-liner, è possibile modificare il tipo di restituzione dell'estensione come lista. Ciò permetterebbe di utilizzare qualcosa come var ids = new List<Guid>().AddIfNotNull(projectId);

+1

Questo non verrà compilato poiché 'T' è' Guid' ma 'projectId' è' Guid? '. Se hai intenzione di creare un metodo di estensione, potresti anche implementare il comportamento desiderato, ad esempio una funzione 'T? -> Lista '. – Lee

+0

@Lee Good point –

0

Se stai andando il percorso metodo di estensione, avrebbe dovuto essere simile:

public static void AddIfNotNull<T>(this List<T> list, T? value) 
    where T : struct 
{ 
    if (value.HasValue) 
    { 
     list.Add(value.Value); 
    } 
} 

Avresti per costruire un secondo metodo di estensione per i tipi di riferimento (where T : class) se necessario.

2

Un'altra idea per un metodo di estensione (il nome potrebbe sicuramente essere migliorato, forse PossiblyCreateSingletonList?):

public static class NullableExtensions 
{ 
    public static List<T> SingletonList<T>(this Nullable<T> item) where T : struct 
    { 
     return item.HasValue ? new List<T> { item.Value } : new List<T>(); 
    } 
} 

Usage:

Guid? projectId = null; 

List<Guid> projectIds = projectId.SingletonList(); // empty list 
Problemi correlati