2008-10-01 9 views
9

Ho scritto una semplice classe di gestione SessionItem per gestire tutti quei fastidiosi controlli null e inserire un valore predefinito se non ne esiste nessuno. Qui è il mio metodo GetItem:C# - Come si definisce un metodo in linea Func <T> come parametro?

public static T GetItem<T>(string key, Func<T> defaultValue) 
{ 
    if (HttpContext.Current.Session[key] == null) 
    { 
     HttpContext.Current.Session[key] = defaultValue.Invoke(); 
    } 
    return (T)HttpContext.Current.Session[key]; 
} 

Ora, come faccio io in realtà uso questo, passando nel Func <T> come parametro del metodo in linea?

risposta

16

Dal momento che è un func, un lambda sarebbe il modo più semplice:

Foo foo = GetItem<Foo>("abc",() => new Foo("blah")); 

Dove [new Foo ("bla")] è il func che viene invocato come predefinito.

Si potrebbe anche semplificare per:

return ((T)HttpContext.Current.Session[key]) ?? defaultValue(); 

Dove ?? è l'operatore a coalescenza nulla - se il primo argomento non è nullo, viene restituito; altrimenti la mano destra viene valutata e restituita (quindi defaultValue() non viene invocato a meno che l'elemento non sia null).

Infine, se si desidera utilizzare il costruttore di default, allora si potrebbe aggiungere un "nuovo()" vincolo:

public static T GetItem<T>(string key) 
    where T : new() 
{ 
    return ((T)HttpContext.Current.Session[key]) ?? new T(); 
} 

Questo è ancora pigro - il nuovo() viene utilizzato soltanto se l'oggetto era nullo

+2

Il ?? la versione non imposta il valore nella sessione. –

2

Perché non si passa direttamente il valore predefinito? A che serve il funtore?

A proposito, defaultValue.Invoke() è piuttosto dettagliato. È anche possibile scrivere semplicemente defaultValue().

+0

Credo che vuole il valore predefinito da valutare solo se necessario, ad es se il valore predefinito è costoso da calcolare. – OregonGhost

+1

Se si passa direttamente il valore predefinito, se il valore predefinito è una nuova istanza di oggetto, creerò quell'oggetto predefinito ogni volta che chiamo GetItem, indipendentemente dal fatto che verrà utilizzato o meno. Mettere in un Func rimanda l'istanziazione solo quando è necessario. – tags2k

+1

Se si ha a che fare con l'istanziazione e se si utilizza il costruttore predefinito, il vincolo generico ": new()" potrebbe essere utile (ho modificato il mio post per includerlo). L'approccio Func è utile se si utilizza un costruttore non predefinito. –

1
var log = SessionItem.GetItem("logger",() => NullLog.Instance) 

nota, di quanto normalmente si può saltare {T} specifica nella {T} chiamata GetItem (se Func {T} restituisce oggetto dello stesso tipo)

Problemi correlati