2012-06-20 11 views
8

Me sorprendió un poco que me di cuenta de que F # 'map implementa IDictionary <' Clave ', Valor> y ICollection<KeyValuePair<'a, 'b>> teniendo en cuenta que ambos admiten la mutación (agregar y eliminar) como parte del contrato.¿Por qué el mapa F # implementa las interfaces con operaciones mutables?

En cuanto a la implementación de map ¡simplemente se exceptúa cuando intentas causar una mutación!

let map = [| (1, "one"); (2, "two") |] |> Map.ofArray 
let dict = map :> IDictionary<int, string> 
dict.Add(3, "three");; 

el código anterior produce la excepción:

System.NotSupportedException: Mapa valores no pueden ser mutados. en Microsoft.FSharp.Collections.FSharpMap 2.System-Collections-Generic-IDictionary 2-Añadir (TKey k, TValue v) a $ FSI_0007.main @(). Detenido debido a un error

que es como se esperaba.

Para que una colección inmutable pueda exponerse como mutable solo para emitir excepciones cuando el consumidor de esa colección intenta causar una mutación parece una decisión tan peligrosa.

¿Falta algo aquí?

+2

La función ['dict'] (http://msdn.microsoft.com/en-us/library/ee353774.aspx) es otro ejemplo. Devuelve un _read only_ 'IDictionary <_,_>'. – Daniel

Respuesta

6

IsReadOnly permite que la interfaz sea de solo lectura a pesar de que proporciona métodos de escritura.

+0

buen punto, aunque le corresponde al consumidor estar siempre revisando el valor de esa propiedad, pero supongo que es lo suficientemente justo – theburningmonk

4

Es una cosa de .Net. No puede implementar solo parte de la interfaz y, sin embargo, desea implementar la interfaz IDictionary`2, ya que puede usar sus métodos de consulta y conversión (para que pueda pasarla a funciones que se leen de IDictionary`2).

9

Creo que la razón principal es que .NET no tiene ninguna interfaz que represente el diccionario inmutable (parte de una interfaz de un). Esto significa que todas las API .NET tienen que tomar IDictionary<K, V> como parámetro, incluso si solo tienen la intención de leer del diccionario. Por lo tanto:

  • La implementación IDictionary<'K, 'V> es casi la única manera de hacer el mapa inmutable F # utilizable como un parámetro para cualquier biblioteca de .NET que necesitan un objeto que soporta las operaciones de búsqueda. Lamentablemente, no existe una alternativa de solo lectura en .NET.

  • Implementar ICollection<KeyValuePair<'K, 'V>> no tiene demasiado sentido para mí, porque hay una alternativa de solo lectura IEnumerable<KeyValuePair<'K, 'V>> y el mapa inmutable también implementa esta interfaz.

    Pero quizás haya algunas librerías .NET que tomen ICollection<'T> (por eficiencias, es decir, para obtener Count sin enumerar todos los elementos) y úselas de forma de solo lectura.

    EDIT: Como señaló Daniel en el comentario, se requiere la implementación de ICollection, ya que la interfaz IDictionary hereda de ella.

creo que la falta de sólo lectura interfaz es bastante desafortunado, pero probablemente no hay manera de que esto podría ser fijo, porque significaría cambiar las bibliotecas de recogida de .NET existentes.

+3

'Map' debe implementar' ICollection > 'porque [' IDictionary <_,_> '] (http://msdn.microsoft.com/en-us/library/s4ys34ea.aspx) lo hereda. – Daniel

+0

@Daniel Gran punto - ¡gracias! Editaré la respuesta. –

Cuestiones relacionadas