2009-09-09 11 views
27

¿Cuáles son las diferencias clave entre Dictionary.Clear y new Dictionary() en C#? ¿Cuál se recomienda para qué casos?Diferencias entre Dictionary.Clear y el nuevo Dictionary()

+0

rendimiento relacionado: [which-is-faster-clear-collection-or-instantiate-new] (http://stackoverflow.com/questions/10901020/which-is-faster-clear-collection-or-instantiate- nuevo) – nawfal

Respuesta

32

Dictionary.Clear() eliminará todos los KeyValue pares en el diccionario. Haciendo new Dictionary() se creará una nueva instancia del diccionario.

Si, y solo si, la versión anterior del diccionario no está enraizada en otra referencia, crear un nuevo diccionario hará que todo el diccionario y sus contenidos (que no están enraizados en otro lugar) puedan ser limpiados por el GC.

Dictionary.Clear() hará que los pares KeyValue estén disponibles para la limpieza.

En la práctica, ambas opciones tenderán a tener efectos muy similares. La diferencia será lo que sucede cuando este se utiliza dentro de un método:

void NewDictionary(Dictionary<string,int> dict) 
{ 
    dict = new Dictionary<string,int>(); // Just changes the local reference 
} 

void ClearDictionary(Dictionary<string,int> dict) 
{ 
    dict.Clear(); 
} 

// When you use this... 
Dictionary<string,int> myDictionary = ...; // Set up and fill dictionary 

NewDictionary(myDictionary); 
// myDictionary is unchanged here, since we made a new copy, but didn't change the original instance 

ClearDictionary(myDictionary); 
// myDictionary is now empty 
+2

@divo - Creo que se refiere a una copia del referencia, no una copia del objeto en sí –

+0

@John: Eso fue exactamente lo que quise decir. Es una copia - una copia de la referencia al diccionario –

0

Dictionary.clear desalojará todos los elementos en su diccionario. El nuevo diccionario crea un nuevo objeto de diccionario en la memoria mientras orfanga su diccionario anterior para que el recolector de basura lo limpie más tarde.

+0

¿Podemos hacer algo mejor que "lo más probable"? Esa va a ser una pregunta clave aquí. –

+0

No creo que el diccionario alguna vez llame a Dispose en los elementos que contiene; si los artículos son desechables, creo que debes escribir un código explícito para desecharlos. – ChrisW

+1

¿Por qué debería llamar a disponer de algo? El hecho de que estén en un diccionario no significa que no estén en uso en otros lugares. Eso sería terriblemente buggy. Todo lo que hace es anular los contenedores de hashtable. – womp

14

Dictionary.Clear()
Esto eliminará todos los pares clave/valor dentro del diccionario. El recolector de basura borrará la memoria de estos elementos durante el siguiente ciclo de recolección de basura. MSDN

nuevo diccionario()
Crea un nuevo objeto diccionario en la memoria y abandona el objeto original. La memoria se borrará durante el próximo Ciclo de recolección de basura.

+0

Ese artículo de MSDN no dice nada sobre la eliminación. –

+3

Algo a tener en cuenta: si su diccionario es muy grande y está seguro de que va a cargar casi lo mismo de datos una vez que esté despejado, el hecho de que Dictionary.Clear() no restablezca la capacidad del diccionario hará es más atractivo. – overslacked

+0

@overslacked - Maldición Acabo de pasar el tiempo escribiendo una respuesta que sugirió exactamente eso. – womp

5

supongo que la diferencia clave es que si se llama a Dictionary.Clear(), se borrarán todas las referencias a ese diccionario. Si usa new Dictionary(), la referencia que está tratando en ese momento se borrará (en cierto sentido), pero no todos los demás lugares que tenga referencias, ya que seguirán refiriéndose al diccionario anterior.

Esperemos que este código se muestra de manera simple:

public void Method() 
{ 
    Dictionary<int, int> d1 = new Dictionary(); 

    d1.Add(1,1); 
    d1.Add(2,3); 

    Dictionary<int, int> d2 = d1; 

    //this line only 'clears' d1 
    d1 = new Dictionary(); 

    d1.Add(1,1); 
    d1.Add(3,5); 
    d2.Add(2,2); 

    //writes '2' followed by '1' 
    Console.WriteLine(d1.Count); 
    Console.WriteLine(d2.Count); 
} 

Si hubiera llamado d1.Clear() lugar, a continuación, D1 y D2 hubiera permanecido en sincronía, y la posterior añade habría añadido a ambos. Las llamadas WriteLine tendrían salida 3 en su lugar.

+0

+1 - esta es la diferencia clave. – Joe

1

Si tiene varias referencias a ese diccionario y las borra, las afectará a todas, ya que si crea un nuevo diccionario, solo afectará a la nueva referencia. Supongo que depende del alcance del impacto que pretendes. Obviamente, una llamada a "nuevo" le dará un diccionario "despejado", pero es posible que pierda otra información de estado útil.

5

Dictionary.Clear eliminará (pero no eliminará) todos los elementos en la instancia, mientras que new Dictionary() creará una nueva instancia que simplemente está vacía. Puede haber algunas sutiles implicaciones entre los dos. Considera los siguientes ejemplos.

void Example1() 
{ 
    var collection = new Dictionary<string, string>(); 
    collection.Add("key1", "value1"); 
    collection.Add("key2", "value2"); 
    foreach (var kvp in collection) 
    { 
    collection = new Dictionary<string, string>(); 
    Console.WriteLine(kvp); 
    } 
} 

void Example2() 
{ 
    var collection = new Dictionary<string, string>(); 
    collection.Add("key1", "value1"); 
    collection.Add("key2", "value2"); 
    foreach (var kvp in collection) 
    { 
    collection.Clear(); 
    Console.WriteLine(kvp); 
    } 
} 

En el primer ejemplo, se imprimirán todos los contenidos de la colección original.Esto se debe a que el enumerador se creó a partir de la variable de referencia antes de reasignarse a una nueva instancia.

En el segundo ejemplo, la colección se borra durante una enumeración que dará como resultado un InvalidOperationException porque la colección se modificó.

19

Como se ha cubierto ampliamente, los efectos son esencialmente los mismos. Clear() y new ambos le daría un diccionario nuevo, esencialmente abandonando las referencias a los objetos dentro de él, liberándolos para ser recogidos si se desrootaron.

Técnicamente, .Clear() tendría una ventaja sobre new si estuviera a punto de repoblar el diccionario al mismo tamaño que antes. Esto se debe a que ya se habría redimensionado internamente para contener la cantidad de objetos que tenía antes. La creación de un nuevo diccionario tendría una nueva tabla hash interna con el tamaño predeterminado, y tendría que volver a expandirse a medida que agrega elementos a ella.

También sugiero que comuniquen una intención completamente diferente, y debe usar .Clear() en su código cuando se trata del mismo contexto que antes. Crear un nuevo diccionario implica que está a punto de emprender una nueva lógica que trata con algo diferente al antiguo diccionario, mientras que usar Clear() indica que sí, que realmente quería restablecer todo lo que ha hecho hasta el momento con él.

+4

> La creación de un nuevo diccionario tendría una nueva tabla hash interna con el tamaño predeterminado; no necesariamente, puede usar una sobrecarga del constructor para establecer la capacidad inicial. – Joe

+4

Sí. Estaba asumiendo solo un .Clear() frente a un nuevo Dictionary(). – womp

3

Creo que se proporcionó .Clear() por lo que si su diccionario está expuesto como una propiedad de solo lectura, podría eliminar todos los elementos. Sin embargo, si no se expone de esa manera, y usted tiene el control completo, entonces podría ser más fácil simplemente crear una instancia de un nuevo diccionario. Puede haber una ligera diferencia de rendimiento entre los dos, también.