2009-08-27 12 views
18

¿Es posible descartar argumentos param en C#? Tengo:Casting C# parámetros de salida?

Dictionary<string,object> dict; // but I know all values are strings 
string key, value; 

En términos generales (y si no tuviera tipos estáticos) que quiero hacer:

dict.TryGetValue(key, out value); 

pero esto obviamente no se compilará porque "no se puede convertir de 'fuera string 'to' out object '".

La solución que estoy usando es:

object valueAsObject; 
dict.TryGetValue(key, out valueAsObject); 
value = (string) valueAsObject; 

pero que parece bastante incómodo.

¿Hay algún tipo de característica de idioma que me permita lanzar un param en la llamada a método, entonces este cambio es para mí? No puedo encontrar ninguna sintaxis que ayude, y parece que no puedo encontrar nada con google.

Respuesta

2

Si conoce todos los valores son cadenas use Dictionary<string, string> en su lugar. El tipo de parámetro de salida se establece por el tipo del segundo parámetro de tipo genérico. Dado que el suyo es actualmente objeto, devolverá un objeto al recuperarlo del diccionario. Si lo cambia a cadena, devolverá cadenas.

+4

El El diccionario es proporcionado por una interfaz que estoy usando. Sé que todos los valores son cadenas para mi uso, porque eso es lo que estoy llenando aquí. – Ken

0

No, no puedes. El código dentro del método está modificando directamente la variable que se le pasó, no se pasa una copia del contenido de la variable.

2

No, no hay forma de evitar eso. El parámetro out debe tener una variable que coincida exactamente.

El uso de una referencia de cadena no es seguro, ya que el diccionario puede contener otras cosas que las cadenas. Sin embargo, si tiene un diccionario de cadenas e intenta usar una variable de objeto en la llamada TryGetValue, eso tampoco funcionará aunque eso sea seguro. El tipo de variable tiene que coincidir exactamente.

18

No sé si es una gran idea, pero se puede añadir un método de extensión genérica:

static bool TryGetTypedValue<TKey, TValue, TActual>(
     this IDictionary<TKey, TValue> data, 
     TKey key, 
     out TActual value) where TActual : TValue 
    { 
     TValue tmp; 
     if (data.TryGetValue(key, out tmp)) 
     { 
      value = (TActual)tmp; 
      return true; 
     } 
     value = default(TActual); 
     return false; 
    } 
    static void Main() 
    { 
     Dictionary<string,object> dict 
      = new Dictionary<string,object>(); 
     dict.Add("abc","def"); 
     string key = "abc", value; 
     dict.TryGetTypedValue(key, out value); 
    } 
+0

Este es un poco interesante de azúcar sintáctico. –

+0

+1 nunca hizo esto en un diccionario, pero tiene algunos métodos de ayuda helper muy similares. –

+1

Lo único que posiblemente consideraría cambiar sería el manejo del caso donde se encuentra el valor pero es del tipo incorrecto. En lugar de tirar, podría querer que simplemente devuelva falso. Por otra parte, puede que no. Tendría que pensar en esto, pero vale la pena mencionarlo. –

2

que utiliza el método de extensión de Marc, pero añade un poco a ella.

Mi problema con el original era que en algunos casos mi diccionario contendría un int64 mientras que yo esperaría un int 32. En otros casos, el diccionario contendría una cadena (por ejemplo, "42") mientras me gustaría obtener es como un int.

No hay manera de manejar la conversión en el método de Marc por lo que añade la capacidad de pasar de un delegado a un método de conversión:

internal static bool TryGetTypedValue<TKey, TValue, TActual>(
     this IDictionary<TKey, TValue> data, 
     TKey key, 
     out TActual value, Func<TValue, TActual> converter = null) where TActual : TValue 
    { 
     TValue tmp; 
     if (data.TryGetValue(key, out tmp)) 
     { 
      if (converter != null) 
      { 
       value = converter(tmp); 
       return true; 
      } 
      if (tmp is TActual) 
      { 
       value = (TActual) tmp; 
       return true; 
      } 
      value = default(TActual); 
      return false; 
     } 
     value = default(TActual); 
     return false; 
    } 

que se puede llamar así:

int limit; 
myParameters.TryGetTypedValue("limitValue", out limit, Convert.ToInt32)