2008-10-01 9 views
9

J'ai écrit une classe de gestion SessionItem simple pour gérer toutes ces vérifications nuls satanés et insérer une valeur par défaut s'il n'en existe aucune. Voici ma méthode de GetItem:C# - Comment définir une méthode en ligne Func <T> en tant que paramètre?

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

Maintenant, comment puis-je utiliser ce fait, en passant dans le Func <T> comme paramètre de la méthode en ligne? Pourquoi ne pas passer la valeur par défaut directement?

Répondre

16

Depuis est une Func, un lambda serait la façon la plus simple:

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

Où [new Foo ("bla")] est le func qui est invoquée par défaut.

Vous pouvez également simplifier à:

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

Où ?? est l'opérateur null-coalescing - si le premier argument est non nul, il est retourné; sinon, la main droite est évaluée et renvoyée (ainsi defaultValue() n'est invoqué que si l'élément est nul).

Enfin, si vous voulez juste utiliser le constructeur par défaut, vous pouvez ajouter une « nouvelle() » contrainte:

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

Ceci est encore paresseux - la nouvelle() est utilisé seulement si l'article était nul.

+2

Le ?? version ne définit pas la valeur dans la session. –

2

Pourquoi? À quoi sert le foncteur? Par ailleurs, defaultValue.Invoke() est assez verbeux. Il est également possible d'écrire simplement defaultValue().

+0

Je suppose qu'il veut la valeur par défaut à évaluer seulement si nécessaire, par exemple si la valeur par défaut est coûteuse à calculer. – OregonGhost

+1

Si je transmets la valeur par défaut directement, alors si la valeur par défaut est une nouvelle instance d'objet, je créerai cet objet par défaut chaque fois que j'appellerai GetItem, qu'il soit ou non utilisé. Mettre dans un Func diffère l'instanciation seulement quand c'est nécessaire. – tags2k

+1

Si vous avez affaire à l'instanciation, et si vous utilisez le constructeur par défaut, alors la contrainte générique ": new()" pourrait être utile (j'ai modifié mon message pour inclure). L'approche Func est utile si vous utilisez un constructeur autre que celui par défaut. –

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

Notez que normalement vous pouvez sauter {T} spécification dans le GetItem {T} appel (si Func {T} retourne l'objet du même type)