tengo un diccionario de tipo
Dictionary<int, (float, float)>cuando trato de leer el valor de él, no puedo usarlo de esta manera
if (myDict.TryGetValue(1, out (float tupleItem1, float tupleItem2))) { /* ... */ }porque luego obtengo errores de compilación
La forma en que funciona es
if (myDict.TryGetValue(1, out (float, float) theTuple)) { /* ... */ }¿Hay alguna manera de que pueda inicializar directamente las variables de esa manera?
if (!myDict.TryGetValue(1, out (float tupleItem1, float tupleItem2))) { /* handle if not found */ tupleItem1 = 111; tupleItem2 = -12345; }Desafortunadamente, aún no puede deconstruir directamente en un parámetro de out , vea esta propuesta .
Tendrás que deconstruirlo tú mismo:
if (!myDict.TryGetValue(1, out var result)) { result = (111, -12345); }Puede mejorar esta situación ligeramente con un método de extensión:
public static class DictionaryExtensions { public static TValue? TryGetValue<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key) where TValue : struct { return dict.TryGetValue(key, out var result) ? result : null; } }Esto te permite escribir:
if (myDict.TryGetValue(1) is not (float tupleItem1, float tupleItem2)) { tupleItem1 = 111; tupleItem2 = -12345; }Si te encuentras haciendo esto mucho, podrías escribir un pequeño método de extensión simple para que sea más legible:
public static class DictionaryExt { public static TValue TryGetValueOrDefault<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key, Func<TValue> getDefault) { return dict.TryGetValue(key, out var value) ? value : getDefault(); } }Entonces su código de muestra podría verse así:
var dict = new Dictionary<int, (float, float)>(); var result = dict.TryGetValueOrDefault(1, () => (111, -12345)); Console.WriteLine(result); Elegí usar Func<TValue> en lugar de TValue para el valor predeterminado para que no tenga que crear un valor predeterminado que no se usará en el caso de que el diccionario ya contenga la clave.
Si desea una sintaxis un poco más simple y no le importa que se cree el valor predeterminado para cada llamada, independientemente de si realmente se necesita, puede escribirlo así:
public static class DictionaryExt { public static TValue TryGetValueOrDefault<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key, TValue defaultValue) { return dict.TryGetValue(key, out var value) ? value : defaultValue; } }Que se llamaría así:
var dict = new Dictionary<int, (float, float)>(); var result = dict.TryGetValueOrDefault(1, (111, -12345)); Console.WriteLine(result); Por supuesto, podría incluir ambos métodos en DictionaryExt para obtener más flexibilidad.
(También es muy posible que la sobrecarga de crear un Func<TValue> para cada llamada sea mayor que crear una tupla para cada llamada, por lo que si le preocupa el rendimiento, debe probarlo. En cualquier caso, puede pasar un Func o Tuple precreados para evitar la sobrecarga de creación).