2012-06-20 17 views
8

Sono rimasto un po 'sorpreso quando ho realizzato che il codice map di F # implementa sia IDictionary <' Chiave ',' Valore> e ICollection<KeyValuePair<'a, 'b>> considerando che entrambi supportano la mutazione (aggiungi e rimuovi) come parte del contratto.Perché la mappa F # implementa le interfacce con operazioni mutabili?

Guardando l'attuazione di map si eccettua semplicemente quando si tenta di provocare mutazioni!

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

il codice precedente genera l'eccezione:

System.NotSupportedException: valori Mappa non possono essere mutati. a Microsoft.FSharp.Collections.FSharpMap 2.System-Collections-Generic-IDictionary 2 Aggiungere (TKey k, TValue v) a $ FSI_0007.main @(). Arrestato causa di un errore

che è come previsto.

Per una collezione immutabile essere in grado di esporre se stessa come mutabile solo per far sorgere un'eccezione quando il consumatore di quella raccolta cerca di provocare una mutazione sembra una decisione così pericolosa.

Mi manca qualcosa qui?

+2

La funzione ['dict'] (http://msdn.microsoft.com/en-us/library/ee353774.aspx) è un altro esempio. Restituisce un _read only_ 'IDictionary <_,_>'. – Daniel

risposta

6

IsReadOnly consente l'interfaccia da sola lettura anche se fornisce metodi scrivibili.

+0

buon punto, anche se cade sul consumatore per controllare sempre il valore di quella proprietà ma suppongo che sia abbastanza giusto – theburningmonk

4

È una cosa .Net. Non è possibile implementare solo alcune delle interfacce, eppure volevano implementare l'interfaccia IDictionary`2 - perché è possibile utilizzare i suoi metodi di interrogazione e conversione (in modo da poterlo passare alle funzioni che leggono da un IDictionary`2).

9

Credo che la ragione principale è che .NET non ha alcuna interfaccia che rappresenta immutabili (parte di un'interfaccia di a) dizionario. Ciò significa che tutte le API .NET devono prendere come parametro IDictionary<K, V>, anche se intendono solo leggere dal dizionario. Quindi:

  • implementazione IDictionary<'K, 'V> è praticamente l'unico modo per rendere la mappa immutabile F # utilizzabile come parametro per le librerie .NET che hanno bisogno di un oggetto che supporta ricerca. Purtroppo, non esiste un'alternativa di sola lettura in .NET.

  • L'implementazione di ICollection<KeyValuePair<'K, 'V>> non ha molto senso per me, poiché esiste un'alternativa di sola lettura IEnumerable<KeyValuePair<'K, 'V>> e la mappa immutabile implementa anche questa interfaccia.

    Ma forse ci sono alcune librerie .NET che prendono ICollection<'T> (per efficienza - cioè per ottenere Count senza enumerare tutti gli elementi) e usarlo in un modo di sola lettura.

    EDIT: Come notato da Daniel nel commento, è necessario attuare ICollection, perché l'interfaccia IDictionary eredita da essa.

penso che la mancanza di sola lettura interfaccia è molto sfortunato, ma probabilmente non c'è modo in cui questo potrebbe essere fissato, perché significherebbe cambiare le librerie .NET di raccolta esistenti.

+3

'Map' deve implementare' ICollection > 'perché [' IDictionary <_,_> '] (http://msdn.microsoft.com/en-us/library/s4ys34ea.aspx) lo eredita. – Daniel

+0

@Daniel Ottimo punto - grazie! Modificherò la risposta. –

Problemi correlati