2011-01-21 8 views
6

Hace LINQ realmente realizar una copia profunda de los resultados a una lista/matriz/etc diferente, o simplemente me da una lista/matriz/etc. compuesto de referencias al original?¿Nueva memoria LINQ al crear devoluciones

+6

Nada en .NET, excepto quizás la serialización, crea automáticamente una copia profunda de cualquier cosa. Una de las razones es que las copias profundas no son triviales para construir automáticamente. – bzlm

+0

@bzlm - entonces cuando edito el resultado de una consulta LINQ, ¿estoy editando el valor del miembro de la colección original? –

+0

Sí, lo eres. Intentalo. :) – bzlm

Respuesta

10

Va a depender de si (y cómo) usar Seleccionar para proyectar los resultados.

Si no crea objetos nuevos en una proyección, el resultado hará referencia a los mismos objetos que la colección original.

Sin embargo, si crea objetos nuevos en el proyecto, obviamente no serán lo mismo.

La colección devuelta aquí contendrá referencias a los mismos objetos en _myCollection:

from m in _myCollection 
where m.SomeFilterCriteria 
select m 

Las colecciones devueltos en estos casos no podrá:

from m in _myCollection 
where m.SomeFilterCriteria 
select new { m.Prop1, m.Prop2 } 

En este caso, vale la pena señalar esa Prop1 y Prop2 del nuevo objeto anónimo - si son tipos de referencia - contendrán una referencia al objeto same como el objeto original. Solo las referencias de nivel superior en la colección serán diferentes.

Básicamente, nada en .Net aparte de los serializadores (como se menciona en otra parte) será una copia "profunda", a menos que lo implemente.

o

from m in _myCollection 
where m.SomeFilterCriteria 
select m.Clone() 

Una vez más, sería un error suponer que cualquier copia "profunda" está pasando aquí. Por supuesto, la implementación de Clone estará en la clase y podría ser cualquier cosa, incluida la copia profunda, pero eso no se da.

+0

En su último ejemplo, pensé 'Clone()' solo realizó una copia superficial. –

+0

Clone copiará sin embargo fue implementado para hacerlo. No hay un clon predeterminado: debe implementarlo para cualquier objeto sobre el que desee admitirlo. Mi respuesta solo habla de las referencias de nivel superior en la colección. Nada de copias "profundas" en .Net. –

+1

@Joel B: para agregar al comentario de qstarin, el [artículo de MSDN] (http://msdn.microsoft.com/en-us/library/system.icloneable.clone.aspx) establece explícitamente que "Clone se puede implementar ya sea como una copia profunda o una copia superficial. "Por lo tanto, no solo se copiará el clon sin embargo se implementó para hacerlo, sino que la copia superficial y profunda son ** ambas ** implementaciones permitidas según la documentación de MSDN. Curiosamente, object tiene un miembro protegido [MemberwiseClone] (http://msdn.microsoft.com/en-us/library/system.object.memberwiseclone.aspx) para hacer copias superficiales. – Brian

2

Lo que devuelve depende mucho del método LINQ al que se refiera. Pero con la excepción de los pocos métodos que copian explícitamente la enumeración (ToList y ToArray por ejemplo), el patrón general es no copiar la entrada a una nueva estructura. En cambio, prefiere la evaluación perezosa.

+1

Si vuelve a leer la pregunta, encontrará que ToList() y ToArray() no son especiales. :) – bzlm

+1

@bzlm, no estoy seguro de cómo la pregunta está relacionada con esa parte de mi respuesta. Quise llamarlos específicamente como 2 métodos LINQ que evalúan ansiosamente la entrada y producen una nueva estructura de colección antes de hacer una declaración más amplia sobre el resto. No dije que hiciera una copia profunda, así que no estoy seguro de a qué se refiere. – JaredPar

+1

@JaredPar La pregunta es "LINQ realmente realiza una copia [...] profunda o simplemente me da una lista [...] compuesta de referencias al original". Su respuesta es si las * enumeraciones * son evaluadas. ¿Derecha? – bzlm

3

LINQ realmente realiza una copia profunda de los resultados a una lista/matriz/etc diferente, o simplemente me da una lista/matriz/etc. compuesto de referencias al original?

De Enumerable.ToArray. (Texto Imagen similar al encontrado Enumerable.ToList)

El ToArray (IEnumerable) fuerzas método de evaluación de la consulta inmediata y devuelve una matriz que contiene los resultados de la consulta. Puede agregar este método a su consulta para obtener una copia en caché de los resultados de la consulta.

Bueno, eso ciertamente parece confuso.

  1. devuelve una matriz que contiene los resultados de la consulta
  2. obtener una copia en caché de la consulta resulta

Desde la primera frase, está claro que no se realizan copias de artículos en la consulta.

De la segunda oración, obtiene una copia de los resultados de la consulta como un todo, pero esa es una copia superficial desde no se hacen copias de los elementos en la consulta.

Cuestiones relacionadas