Pregunta sobre casting, generics, interface, c# – Interfaces anidadas: Cast IDictionary <TKey, IList <TValue>> to IDictionary <TKey, IEnumerable <TValue>>?

1

Creo que es bastante sencillo lanzar unIDictionary<TKey, IList<TValue>> objetar a unIDictionary<TKey, IEnumerable<TValue>>, pero

<code>var val = (IDictionary<TKey, IEnumerable<TValue>>)Value;
</code>

arroja unSystem.InvalidCastExceptiony

<code>var val = Value as IDictionary<TKey, IEnumerable<TValue>>;
</code>

haceval nulo. ¿Cuál es la forma correcta de lanzar esto?

Tu respuesta

2   la respuesta
0

Esto puede o no puede ayudarte, pero pensé que lo tiraría como un suplemento a la respuesta de Jon.

Si todo lo que necesitas es el diccionario.valores, sin hacer referencia a sus claves, puedes hacer esto:

<code>IDictionary<TKey, IList<TValue>> dictionary = Whatever();
var values = (IEnumerable<IEnumerable<TValue>>)dictionary.Values;
</code>

Para que esto funcione, debe utilizar C # 4.0 o posterior, y TValue debe estar restringido para ser un tipo de referencia. Aquí está el código, ligeramente refactorizado, y con comentarios para explicar:

<code>IDictionary<TKey, IList<TValue>> dictionary = Whatever();

//Values returns an ICollection<IList<TValue>>
ICollection<IList<TValue>> temp1 = dictionary.Values;

//ICollection<T> inherits from IEnumerable<T>
IEnumerable<IList<TValue>> temp2 = temp1;

//IEnumerable<T> is covariant
//There is an implicit reference conversion between IList<T> and IEnumerable<T>
//So there is an implicit reference conversion between IEnumerable<IList<T>>
//and IEnumerable<IEnumerable<T>>
IEnumerable<IEnumerable<TValue>> values = temp2;
</code>
7

Creo que es bastante sencillo lanzar unIDictionary<TKey, IList<TValue>> objetar a unIDictionary<TKey, IEnumerable<TValue>>

Absolutamente no. No sería de tipo seguro. Aquí hay un ejemplo de por qué no:

<code>// This is fine...
IDictionary<string, IList<int>> dictionary = new Dictionary<string, IList<int>>();

// Suppose this were valid...
IDictionary<string, IEnumerable<int>> badDictionary = dictionary;

// LinkedList<T> doesn't implement IList<T>
badDictionary["foo"] = new LinkedList<int>();

// What should happen now?
IList<int> bang = dictionary["foo"];
</code>

Como puede ver, eso va a causar problemas, estaríamos tratando de obtener unLinkedList<int> cuando esperamos que todos los valores se implementenIList<int>. El punto de los genéricos es ser de tipo seguro: ¿qué línea esperaría que falle? Las líneas primera, tercera y cuarta me parecen claramente válidas, por lo que la segunda es lasolamente uno que puede fallar en compilar, y lo hace ...

Ahora enalgunos Casos, se puede hacer de forma segura. Por ejemplo, puede convertir (en C # 4) desdeIEnumerable<string> aIEnumerable<object> porqueIEnumerable<T> solo utilizaT en posiciones de "salida".

VerMSDN para más detalles.

EDITAR: Solo para aclarar - es fácil crear unnuevo diccionario con una copia de los pares clave / valor existentes, por ejemplo, usando el enlace:

<code>var copy = original.ToDictionary<TKey, IEnumerable<TValue>>(pair => pair.Key,
                                                            pair => pair.Value);
</code>

Solo debe tener en cuenta que ahora tiene dos diccionarios separados.

@JeremyHolovacs: Bueno, no es que las cosas se agreguen en dos lugares, es que solo hay un objeto y los valores de ambas variables se refieren al mismo objeto. Como tener dos hojas de papel con la misma dirección de casa escrita en ellas. No puedes hacer esta conversión, simplemente sería inseguro hacerlo. Quiero decir, podrías escribir tu propia implementación de solo lectura deIDictionary<TKey, TValue> lo que delegó a otro, pero sería desagradable ... Si pudiera decirnos lo que estaba tratando de lograr (en general), podríamos ayudarlo más. Jon Skeet
Veo, porque el objeto del diccionario es de naturaleza referencial, agregando el valor abadDictionary lo agrega adictionary. ¿Cómo se puede evitar esto entonces? Como puedo conseguir miIDictionary<TKey, IEnumerable<TValue>>? Jeremy Holovacs
Bueno, parece que la respuesta a esta pregunta es "No es posible". Es posible que luego haga otra pregunta sobre cómo hacer lo que quiero, pero simplemente puedo cambiar lo que quiero hacer. Jeremy Holovacs
@JeremyHolovacs: Vea mi edición: si está lo suficientemente contento de tomar una copia, es simple. Pero no se puede "ver" un diccionario de un tipo como un diccionario de anohter. Jon Skeet

Preguntas relacionadas