values new example c# java .net collections dictionary

new - return dictionary c#



¿Tiene C#una manera de darme un diccionario inmutable? (13)

"Fuera de la caja" no hay una manera de hacer esto. Puede crear uno derivando su propia clase de diccionario e implementando las restricciones que necesita.

¿Hay algo incorporado en las bibliotecas centrales de C # que pueda darme un diccionario inmutable?

Algo parecido a Java :

Collections.unmodifiableMap(myMap);

Y solo para aclarar, no estoy buscando detener el cambio de las claves / valores mismos, solo la estructura del Diccionario. Quiero algo que falle rápido y fuerte si se llama a cualquiera de los métodos del mutador de IDictionary ( Add, Remove, Clear ).


Añadiendo a la respuesta de dbkk , quería poder usar un inicializador de objetos cuando primero creaba mi ReadOnlyDictionary. Hice las siguientes modificaciones:

private readonly int _finalCount; /// <summary> /// Takes a count of how many key-value pairs should be allowed. /// Dictionary can be modified to add up to that many pairs, but no /// pair can be modified or removed after it is added. Intended to be /// used with an object initializer. /// </summary> /// <param name="count"></param> public ReadOnlyDictionary(int count) { _dict = new SortedDictionary<TKey, TValue>(); _finalCount = count; } /// <summary> /// To allow object initializers, this will allow the dictionary to be /// added onto up to a certain number, specifically the count set in /// one of the constructors. /// </summary> /// <param name="key"></param> /// <param name="value"></param> public void Add(TKey key, TValue value) { if (_dict.Keys.Count < _finalCount) { _dict.Add(key, value); } else { throw new InvalidOperationException( "Cannot add pair <" + key + ", " + value + "> because " + "maximum final count " + _finalCount + " has been reached" ); } }

Ahora puedo usar la clase así:

ReadOnlyDictionary<string, string> Fields = new ReadOnlyDictionary<string, string>(2) { {"hey", "now"}, {"you", "there"} };


Con el lanzamiento de .NET 4.5, hay una nueva clase ReadOnlyDictionary . Simplemente IDictionary un IDictionary al constructor para crear el diccionario inmutable.

Here hay un método de extensión útil que se puede utilizar para simplificar la creación del diccionario de solo lectura.


Desde Linq, hay una interfaz genérica ILookup . Lea más en MSDN .

Por lo tanto, para obtener simplemente un diccionario inmutable, puede llamar a:

using System.Linq; // (...) var dictionary = new Dictionary<string, object>(); // (...) var read_only = dictionary.ToLookup(kv => kv.Key, kv => kv.Value);


En general, es una idea mucho mejor no pasar ningún diccionario en primer lugar (si no TIENE que hacerlo).

En su lugar, cree un objeto de dominio con una interfaz que no ofrezca ningún método que modifique el diccionario (que se ajusta). En cambio, ofrece el método LookUp requerido que recupera elementos del diccionario por clave (además, es más fácil de usar que un diccionario).

public interface IMyDomainObjectDictionary { IMyDomainObject GetMyDomainObject(string key); } internal class MyDomainObjectDictionary : IMyDomainObjectDictionary { public IDictionary<string, IMyDomainObject> _myDictionary { get; set; } public IMyDomainObject GetMyDomainObject(string key) {.._myDictionary .TryGetValue..etc...}; }




La biblioteca de código abierto PowerCollections incluye un contenedor de diccionario de solo lectura (así como contenedores de solo lectura para casi todo lo demás), accesible a través de un método ReadOnly() estático ReadOnly() en la clase Algorithms .


No lo creo. Hay una manera de crear una lista de solo lectura y una colección de solo lectura, pero no creo que haya un diccionario incorporado de solo lectura. System.ServiceModel tiene una implementación ReadOnlyDictinoary, pero es interna. Sin embargo, probablemente no sería demasiado difícil copiarlo, utilizando Reflector, o simplemente crear uno propio desde cero. Básicamente envuelve un diccionario y lanza cuando se llama un mutador.


No, pero un envoltorio es bastante trivial:

public class ReadOnlyDictionary<TKey, TValue> : IDictionary<TKey, TValue> { IDictionary<TKey, TValue> _dict; public ReadOnlyDictionary(IDictionary<TKey, TValue> backingDict) { _dict = backingDict; } public void Add(TKey key, TValue value) { throw new InvalidOperationException(); } public bool ContainsKey(TKey key) { return _dict.ContainsKey(key); } public ICollection<TKey> Keys { get { return _dict.Keys; } } public bool Remove(TKey key) { throw new InvalidOperationException(); } public bool TryGetValue(TKey key, out TValue value) { return _dict.TryGetValue(key, out value); } public ICollection<TValue> Values { get { return _dict.Values; } } public TValue this[TKey key] { get { return _dict[key]; } set { throw new InvalidOperationException(); } } public void Add(KeyValuePair<TKey, TValue> item) { throw new InvalidOperationException(); } public void Clear() { throw new InvalidOperationException(); } public bool Contains(KeyValuePair<TKey, TValue> item) { return _dict.Contains(item); } public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) { _dict.CopyTo(array, arrayIndex); } public int Count { get { return _dict.Count; } } public bool IsReadOnly { get { return true; } } public bool Remove(KeyValuePair<TKey, TValue> item) { throw new InvalidOperationException(); } public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() { return _dict.GetEnumerator(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return ((System.Collections.IEnumerable)_dict).GetEnumerator(); } }

Obviamente, puede cambiar el setter anterior [] si desea permitir la modificación de valores.


Podrías probar algo como esto:

private readonly Dictionary<string, string> _someDictionary; public IEnumerable<KeyValuePair<string, string>> SomeDictionary { get { return _someDictionary; } }

Esto eliminaría el problema de mutabilidad a favor de que tu interlocutor deba convertirlo a su propio diccionario:

foo.SomeDictionary.ToDictionary(kvp => kvp.Key);

... o utilice una operación de comparación en la clave en lugar de una búsqueda de índice, por ejemplo:

foo.SomeDictionary.First(kvp => kvp.Key == "SomeKey");


También hay otra alternativa como la que describí en:

http://www.softwarerockstar.com/2010/10/readonlydictionary-tkey-tvalue/

Esencialmente es una subclase de ReadOnlyCollection>, que hace el trabajo de una manera más elegante. Elegante en el sentido de que tiene soporte en tiempo de compilación para hacer que el diccionario sea de solo lectura en lugar de arrojar excepciones desde los métodos que modifican los elementos dentro de él.


Una solución podría ser, lanzar una nueva lista de KeyValuePair del Diccionario para mantener el original sin modificaciones.

var dict = new Dictionary<string, string>(); dict.Add("Hello", "World"); dict.Add("The", "Quick"); dict.Add("Brown", "Fox"); var dictCopy = dict.Select( item => new KeyValuePair<string, string>(item.Key, item.Value)); // returns dictCopy;

De esta forma, el diccionario original no se modificará.