Compara dos listas para las diferencias

Me gustaría recibir algunos comentarios sobre cómo podemos escribir mejor una función genérica que permita comparar dos listas. Las listas contienen objetos de clase y nos gustaría iterar a través de una lista, buscando el mismo elemento en una segunda lista e informar cualquier diferencia.

Ya tenemos un método para comparar clases, por lo que necesitamos comentarios sobre cómo podemos alimentar el método (que se muestra a continuación) de dos listas.

Por ejemplo, supongamos que tenemos una clase simple de “Empleado” que tiene tres propiedades, Nombre, ID, Departamento. Queremos informar las diferencias entre List y otra lista.

Nota:
Ambas listas contendrán siempre la misma cantidad de elementos.

Como mencionamos anteriormente, tenemos un método genérico que usamos para comparar dos clases, ¿cómo podemos incorporar este método para atender listas, es decir, desde otro método, recorrer la Lista y alimentar las clases al método genérico … pero ¿Cómo encontramos la clase equivalente en la segunda lista para pasar al siguiente método;

public static string CompareTwoClass_ReturnDifferences(T1 Orig, T2 Dest) where T1 : class where T2 : class { // Instantiate if necessary if (Dest == null) throw new ArgumentNullException("Dest", "Destination class must first be instantiated."); var Differences = CoreFormat.StringNoCharacters; // Loop through each property in the destination foreach (var DestProp in Dest.GetType().GetProperties()) { // Find the matching property in the Orig class and compare foreach (var OrigProp in Orig.GetType().GetProperties()) { if (OrigProp.Name != DestProp.Name || OrigProp.PropertyType != DestProp.PropertyType) continue; if (OrigProp.GetValue(Orig, null).ToString() != DestProp.GetValue(Dest, null).ToString()) Differences = Differences == CoreFormat.StringNoCharacters ? string.Format("{0}: {1} -> {2}", OrigProp.Name, OrigProp.GetValue(Orig, null), DestProp.GetValue(Dest, null)) : string.Format("{0} {1}{2}: {3} -> {4}", Differences, Environment.NewLine, OrigProp.Name, OrigProp.GetValue(Orig, null), DestProp.GetValue(Dest, null)); } } return Differences; } 

¿Alguna sugerencia o idea apreciada?

Editar: Targeting .NET 2.0 por lo que LINQ está fuera de cuestión.

…. pero ¿cómo encontramos la clase equivalente en la segunda lista para pasar al siguiente método;

Este es su problema real; debe tener al menos una propiedad inmutable, una identificación o algo así, para identificar los objetos correspondientes en ambas listas. Si no tiene esa propiedad, no puede resolver el problema sin errores. Puede tratar de adivinar los objetos correspondientes buscando cambios mínimos o lógicos.

Si tiene esa propiedad, la solución se vuelve realmente simple.

 Enumerable.Join( listA, listB, a => a.Id, b => b.Id, (a, b) => CompareTwoClass_ReturnDifferences(a, b)) 

gracias a ustedes, Danbruc y Noldorin por sus comentarios. ambas Listas tendrán la misma longitud y en el mismo orden. por lo que el método anterior está cerca, pero ¿puedes modificar este método para pasar la enumeración actual del método que publiqué anteriormente?

Ahora estoy confundido … ¿cuál es el problema con eso? ¿Por qué no solo lo siguiente?

 for (Int32 i = 0; i < Math.Min(listA.Count, listB.Count); i++) { yield return CompareTwoClass_ReturnDifferences(listA[i], listB[i]); } 

La llamada Math.Min () incluso puede omitirse si se garantiza la misma longitud.


La implementación de Noldorin es, por supuesto, más inteligente debido al delegado y el uso de enumeradores en lugar de usar ICollection.

Esta solución produce una lista de resultados, que contiene todas las diferencias de ambas listas de entrada. Puede comparar sus objetos por cualquier propiedad, en mi ejemplo es ID. La única restricción es que las listas deben ser del mismo tipo:

 var DifferencesList = ListA.Where(x => !ListB.Any(x1 => x1.id == x.id)) .Union(ListB.Where(x => !ListA.Any(x1 => x1.id == x.id)));