2011-03-01 8 views
5

Un compañero de trabajo mío vino a través de esto el otro día mientras estábamos trabajando en la mejora de un proyecto a .NET 4.OrderedDictionary ¿cambio de última hora en .Net 4?

Dado el siguiente código:

var od = new System.Collections.Specialized.OrderedDictionary(); 

od.Add("key1", "value1"); 
od.Add("key2", "value2"); 

foreach (System.Collections.DictionaryEntry entry in od) 
{ 
    od[entry.Key] = null; 
} 

En .Net 3.5, el establecimiento de una entrada a null funcionará bien. Como se esperaba, la clave aún estaría en el diccionario, y su valor coincidente sería nulo.

En .Net 4.0, esto arroja una InvalidOperationException que dice "La colección fue modificada, la operación de enumeración puede no ejecutarse".

Pensé que tal vez había un cambio en OrderedDictionary donde establecer una entrada a null lo eliminaría por completo, pero haciendo una prueba rápida dice que la entrada todavía está allí cuando la configura en nulo.

¿Se trata de un cambio radical que no se ha informado?

+0

¿Estás seguro de que el problema no está en tratar de cambiar la entrada desde un bucle 'foreach', en lugar de simplemente establecerlo en' nulo'? – Oded

Respuesta

6

http://msdn.microsoft.com/en-us/library/system.collections.specialized.ordereddictionary(v=VS.90).aspx

La instrucción foreach es una envoltura alrededor del encuestador, que sólo permite la lectura desde, no escribir, la compilación.

Creo que significa que la estaba usando incorrectamente y que es su culpa que la estuviera usando de esta manera. No se suponía que funcionara y no funciona ahora.

+0

Gracias por esto (y por todos los demás que respondieron).¡No puedo creer que lo haya pasado por alto en la documentación! – rossisdead

0

El error no tiene nada que ver con null. Tiene todo que ver con el hecho de que está modificando la colección en un ciclo foreach. Hacerlo invalida el iterador y rompe el proceso de enumeración.

Puede establecer con seguridad el valor en nulo (para tipos de valores que se pueden nulos), fuera de del foreach.

decir esto funcionará:

od.Add("key2", null);

7

Ha encontrado un cambio importante. En versiones anteriores de OrderedDictionary, la clase interna OrderedDictionaryEnumerator usaba índices de matriz para atravesar la matriz. Siempre y cuando los artículos no estén eliminados o añadidos, no se quejarán.

La nueva versión utiliza el enumerador subyacente que la matriz devuelve a través de GetEnumerator, y es por eso que está viendo el código fallar.

Dicho esto, es solo un cambio de rotura que nunca debería haber funcionado para comenzar con. Es totalmente ilegal modificar, de cualquier forma, una colección sobre la que está enumerando, ya sea a través de un bucle foreach o utilizando el IEnumerator explícitamente. Lo que encontraste fue un error que fue corregido.

+0

A pesar de la manera en que se documenta la enumeración, existe una tradición de larga data de que un enumerador puede permanecer funcional cuando se modifique la colección de origen siempre que se comporte de manera sensata. Algo como el enumerador en 'ConcurrentDictionary <,>' sería bastante inútil sin esa capacidad. – supercat

4

Es una corrección de errores. El artículo de comentarios que desencadenó la corrección is here.

+0

Es decir, estaba * arreglado * en .NET 4.0 (tuve que leer la publicación tres veces para entenderlo :-) –