2008-10-31 15 views
15

Actualmente estoy usandoC# diccionarios ValueOrNull/ValueorDefault

var x = dict.ContainsKey(key) ? dict[key] : defaultValue 

me gustaría alguna manera de tener el diccionario [clave] volver nula para las llaves inexistente, por lo que podría escribir algo así como

var x = dict[key] ?? defaultValue; 

esto también termina siendo parte de las consultas de linq, etc. por lo que preferiría soluciones de una sola línea.

+0

Las respuestas actuales son correctas, y ver también [mi pregunta similar] (http://stackoverflow.com/questions/6214975), que es más una discusión. Sin embargo, debe evitar 'dict.ContainsKey (clave)? dict [tecla] 'mientras busca el diccionario dos veces, una para el' ContainsKey' y otra para el indexer '[]'. 'TryGetValue' es feo y no en línea, pero es una operación única. – Keith

Respuesta

21

Con un método de extensión:

public static class MyHelper 
{ 
    public static V GetValueOrDefault<K, V>(this IDictionary<K, V> dic, 
              K key, 
              V defaultVal = default(V)) 
    { 
     V ret; 
     bool found = dic.TryGetValue(key, out ret); 
     if (found) { return ret; } 
     return defaultVal; 
    } 
    void Example() 
    { 
     var dict = new Dictionary<int, string>(); 
     dict.GetValueOrDefault(42, "default"); 
    } 
} 
+4

I Ofrecería una sobrecarga que devuelva el valor predeterminado (V) – Will

+4

En C# 4 ahora puede hacer que el parámetro predeterminado sea opcional: V defaultVal = default (V). Entonces no tiene que pasar por defecto si no quiere: si no se encuentra el valor, obtendrá el valor predeterminado para el tipo V. – Tevin

+0

@Tevin puede proporcionar un enlace a msdn/artículo que documenta este comportamiento? No estoy familiarizado con .NET 4, pero el operador predeterminado en un tipo de referencia en .NET 3.5 devuelve nulo y por defecto en un tipo de valor devuelve el valor usando el constructor no-args. Dudo que esto haya cambiado? – toong

6

Se puede utilizar un método de ayuda:

public abstract class MyHelper { 
    public static V GetValueOrDefault<K,V>(Dictionary<K,V> dic, K key) { 
     V ret; 
     bool found = dic.TryGetValue(key, out ret); 
     if (found) { return ret; } 
     return default(V); 
    } 
} 

var x = MyHelper.GetValueOrDefault(dic, key); 
+0

También se puede hacer trivialmente un método de extensión, por lo que puede hacer dict.GetValueOrDefault (clave) – stevemegson

+0

Creo que lo hizo en primer lugar ... Es extraño que la única diferencia sea la palabra clave "this". – Will

+3

En realidad, puede hacer que esto sea incondicional; simplemente devuelva ret después de la llamada a TryGetValue. Estará predeterminado (V) si el método devuelve falso. –

0

no es simplemente TryGetValue(key, out value) lo que está buscando? Citando MSDN:

When this method returns, contains the value associated with the specified key, if the key is found; otherwise, the default value for the type of the value parameter. This parameter is passed uninitialized. 

de http://msdn.microsoft.com/en-us/library/bb347013(v=vs.90).aspx

+0

Estaba buscando una expresión de una sola línea. El problema con 'TryGetValue' es que 1) es una declaración. 2) requiere una declaración anterior de la variable 'out'. – Jimmy

4

Aquí está la solución "definitiva", en el que se implementa como un método de extensión, utiliza la interfaz IDictionary, proporciona un valor predeterminado opcional, y está escrito de manera concisa.

public static TV GetValueOrDefault<TK, TV>(this IDictionary<TK, TV> dic, TK key, 
    TV defaultVal=default(TV)) 
{ 
    TV val; 
    return dic.TryGetValue(key, out val) 
     ? val 
     : defaultVal; 
}