2010-06-24 21 views
33

En .NET Framework, muchas de las clases System.Collection tienen métodos Clear. ¿Hay una clara ventaja al usar esto versus reemplazar la referencia con un nuevo objeto?Usando el método "borrar" contra el nuevo objeto

Gracias.

+0

posible duplicado de [¿Cuáles son las diferencias clave entre Dictionary.clear y el nuevo Dictionary() en C#?] (Http://stackoverflow.com/questions/1400532/what-are-the-key-differences-between- dictionary-clear-and-new-dictionary-in-c) – nawfal

Respuesta

39

Desea usar Clear si tiene otras referencias al mismo objeto, y desea que sigan apuntando al mismo objeto.

Por ejemplo, quizás tenga una cola de trabajo donde almacena tareas para hacer. Y en uno o más hilos saca los elementos de trabajo de esta cola (por supuesto, usa el bloqueo para asegurarse de que acceda a la cola con un hilo como máximo). Si en algún momento desea vaciar la cola, puede usar Clear y todos los hilos seguirán apuntando al mismo objeto.

Como seen here cuando se utiliza Clear todos los artículos serán eliminados, y el Count serán 0, pero el Capacity permanecerán sin cambios. Por lo general, el Capacity no ha cambiado es algo bueno (por su eficiencia), pero podría haber casos extremos en los que haya toneladas de elementos y desee que la memoria se libere finalmente.

El enlace MSDN anterior también menciona que Borrar es una operación O (n). Mientras que simplemente reemplazar la referencia será una operación O (1) y luego, eventualmente, será recogida de basura, pero posiblemente no de inmediato. Pero reemplazar la referencia también significa que la memoria que conforma la capacidad deberá ser reasignada.

+2

Esto obtuvo la mayor parte, lo único que quiero agregar es que desea utilizar Clear cuando se trata de ObservableCollections que ya se están viendo. – Rangoric

3

sustitución de la referencia no se dará a conocer la colección de inmediato que tendrá que esperar a recolector de basura para disponer del objeto,

si desea volver a utilizar la misma colección de objetos del uso claro si no tendrá los dos objetos en la memoria por un tiempo.

+0

Aunque esto es cierto, esta no es la diferencia que le importa a la mayoría de las personas. –

+0

@ IgnacioVazquez-Abrams depende. Sin duda me importaría si la colección es muy grande. – nawfal

6

Brian es correcto, pero para ser más específicos, el método Clear elimina todos los elementos de la instancia actual de la colección. La instancia de una nueva colección y la asignación de su referencia a su variable le dará una instancia completamente nueva y puede causar algunas consecuencias no deseadas dependiendo de si otras personas mantienen una referencia a la instancia anterior. Si otro hilo tiene una referencia a esa colección, ellos mantendrán una referencia a la colección anterior aunque hayas creado una nueva instancia.

3

Eso dependerá tal vez de qué tan grande sea su objeto de colección. Creo que cuando diga "new" creará el tamaño original del objeto, "clear" borrará el contenido, pero el tamaño seguirá siendo el mismo.

1

El objeto nuevo causa problemas de memoria si trabaja en datos grandes y manipula el elemento IEnumerable con frecuencia. Mire mi ejemplo:

class Lol 
{ 
    int i; 
    string s; 
    public Lol(int ti, string ts) 
    { 
     i = ti; 
     s = ts; 
    } 
} 

class Program 
{ 
    static List<Lol> lol = new List<Lol>(); 

    static void Main(string[] args) 
    { 
     for (int i = 0; i < 10000000; ++i) 
      lol.Add(new Lol(i, i.ToString())); 

     Stopwatch sw = new Stopwatch(); 
     sw.Start(); 
     ListCleaner(); 
     sw.Stop(); 
     Console.WriteLine(sw.ElapsedMilliseconds); 

     for (int i = 0; i < 10000000; ++i) 
      lol.Add(new Lol(i, i.ToString())); 

     Console.WriteLine("lol"); 

     ListCleaner(); 

     for (int i = 0; i < 10000000; ++i) 
      lol.Add(new Lol(i, i.ToString())); 

     Console.WriteLine("lol"); 

     ListCleaner(); 

     for (int i = 0; i < 10000000; ++i) 
      lol.Add(new Lol(i, i.ToString())); 

     Console.WriteLine("lol"); 

     ListCleaner(); 

     for (int i = 0; i < 10000000; ++i) 
      lol.Add(new Lol(i, i.ToString())); 

     Console.WriteLine("lol"); 

     ListCleaner(); 

     for (int i = 0; i < 10000000; ++i) 
      lol.Add(new Lol(i, i.ToString())); 

     Console.WriteLine("lol"); 

     ListCleaner(); 

     for (int i = 0; i < 10000000; ++i) 
      lol.Add(new Lol(i, i.ToString())); 

     Console.WriteLine("lol"); 

     ListCleaner(); 

     for (int i = 0; i < 10000000; ++i) 
      lol.Add(new Lol(i, i.ToString())); 

     Console.WriteLine("lol"); 

     ListCleaner(); 

     for (int i = 0; i < 10000000; ++i) 
      lol.Add(new Lol(i, i.ToString())); 

     Console.WriteLine("lol"); 

     ListCleaner(); 
    } 

    static void ListCleaner() 
    { 
     //lol = new List<Lol>(); 
     lol.Clear(); 
    } 
} 

Si utiliza esto, no encontrará ningún problema en el tiempo de ejecución. Pero si comenta Line clara en ListCleaner y descomenta nueva línea de objeto, tendrá un problema de memoria.

Por cierto "Console.WriteLine (sw.ElapsedMilliseconds);" (Puede usar ElapsedTicks porque su valor es radicalmente diferente que el otro.) Line le dice que Clear toma más tiempo pero le ahorra problemas de memoria.

Me di cuenta de que todo esto sucede en el código de depuración (incluso para el modo de lanzamiento). No hay problema en ejecutar el archivo .exe.

Cuestiones relacionadas