2010-09-28 10 views
3

On m'a demandé ce qui est erroné/comment le scénario suivant peut être fixéExtension « WhenNull » pour vérifier null et init l'objet sous-jacent via lambda

Customer customer = null; 
customer.WhenNull(c => new Customer()) 
     .Foo(); 

// instead of 
Customer customer = null; 
if (customer == null) 
{ 
    customer = new Customer(); 
} 
customer.Foo(); 

Un développeur me envoie sa version de la WhenNull l'extension

public static T WhenNull<T>(this T source, Action<T> nullAction) 
{ 
    if (source != null) 
    { 
     return source; 
    } 

    if (nullAction == null) 
    { 
     throw new ArgumentNullException("nullAction"); 
    } 

    nullAction(source); 

    return source; 
} 

Son problème/l'intention est qu'il ne veut pas spécifier l'objet sous-jacent dans l'expression lambda (dans ce cas, « client »)

Customer customer = null; 
customer.WhenNull(c => customer = new Customer()) 
     .Foo(); 

Je pensais que cela ne pouvait pas être fait.
Est-ce correct?

+1

Je me suis un peu perdue - laquelle voulez-vous atteindre? Lequel a tort? – Grzenio

Répondre

7

Vous pouvez faire:

static T WhenNull<T>(this T t) where T : class, new() 
{ 
    return t ?? new T(); 
} 

a également noté: Vous voulez utiliser Func<T> pas Action<T> selon votre code d'exemple.

Edit 2:

Vous voulez sans doute ceci:

static T WhenNull<T>(this T t, Func<T> init) where T : class 
{ 
    if (t == null) 
    { 
    t = init(); // could return here, but for debugging this is easier 
    } 
    return t; 
} 

Utilisation:

something.WhenNull(() => new Something()).Foo() 
+1

+1 pour ajouter une contrainte 'class'. Cependant, la contrainte 'new()' ne devrait pas être nécessaire dans la deuxième variante. – Lucero

2

Si vous voulez vraiment une syntaxe abrégée, vous pouvez simplement faire:

(customer = customer ?? new Customer()).Foo(); 

Ne reco Mêlez-le bien.

+0

alternativement (client ?? (client = nouveau client()). Foo() – veggerby

0

Vous pouvez utiliser Func < T> à la place:

public static T WhenNull<T>(this T source, Func<T> nullFunc) 
{ 
    if (source != null) 
    { 
     return source; 
    } 

    if (nullFunc == null) 
    { 
     throw new ArgumentNullException("nullFunc"); 
    } 

    return nullFunc(); 
} 

Ou comme les États leppie utilisent l'opérateur coalescent et le nouveau contraint() si vous ne voulez pas spécifier le lamba.

+1

Pas pu, mais devrait! :) – leppie

+0

@leppie true :) – veggerby