2008-10-01 9 views
9

Ich habe eine einfache SessionItem-Management-Klasse geschrieben, um alle diese lästigen Null-Checks zu behandeln und einen Standardwert einzufügen, wenn keiner existiert. Hier ist meine GetItem Methode:C# - Wie definiere ich eine Inline-Methode Func <T> als Parameter?

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]; 
} 

Nun, wie kann ich dies auch tatsächlich nutzen, vorbei in den Func <T> als Inline-Methodenparameter?

Antwort

16

Da, dass eine func ist, wäre eine Lambda der einfachste Weg sein:

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

Wo [new Foo ("blah")] ist die func, der als Standard aufgerufen wird.

Sie könnten auch vereinfachen:

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

Wo ?? ist der Nullkoaleszenzoperator - wenn das erste Argument nicht null ist, wird es zurückgegeben; Andernfalls wird die rechte Hand ausgewertet und zurückgegeben (dh defaultValue() wird nur aufgerufen, wenn das Element null ist). - die neue() nur dann, wenn das Element verwendet

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

Dies ist immer noch faul:

Schließlich, wenn Sie nur den Standard-Konstruktor verwenden möchten, dann könnte man eine „neue()“ Constraint hinzufügen war null.

+2

Die ?? Version legt den Wert in der Sitzung nicht fest. –

2

Warum übergeben Sie den Standardwert nicht direkt? Was nützt der Funktor?

Übrigens ist defaultValue.Invoke() ziemlich ausführlich. Es ist auch möglich, einfach defaultValue() zu schreiben.

+0

Ich glaube, er den Standardwert will nur bei Bedarf ausgewertet werden, z wenn der Standardwert teuer zu berechnen ist. – OregonGhost

+1

Wenn ich den Standardwert direkt übergebe, wird das Standardobjekt bei jedem Aufruf von GetItem automatisch erstellt, unabhängig davon, ob es verwendet wird oder nicht. Putting in einem Func verschiebt die Instanziierung nur, wenn es benötigt wird. – tags2k

+1

Wenn Sie mit Instanziierung arbeiten und wenn Sie den Standardkonstruktor verwenden, dann könnte die generische Einschränkung ": new()" hilfreich sein (Ich habe meinen Beitrag zum Einschließen bearbeitet). Der Func Ansatz ist nützlich, wenn Sie einen nicht standardmäßigen Konstruktor verwenden. –

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

Hinweis, als normalerweise kann man überspringen {T} Spezifikation in der GetItem {T} Anruf (wenn Func {T} Objekt des gleichen Typs zurückgibt)