Union de Linq, nos permite unir el contenido de diferentes arreglos en uno solo, comparando el objeto completo,veamos un ejemplo:
Creamos una clase con dos campos.
public class Foo
{
public string Campo1;
public string Campo2;
public Foo(string pCampo1, string pCampo2)
{
this.Campo1 = pCampo1;
this.Campo2 = pCampo2;
}
}
public class TestFoo
{
public TestFoo()
{
//Creamos dos Arreglos, para Testear.
List<Foo> foo = new List<Foo>()
{ new Foo("campo1", "campo22"),
new Foo("campo3", "campo3"),
new Foo("campox", "campoy") };
List<Foo> foo2 = new List<Foo>()
{ new Foo("campo11", "campo22"),
new Foo("campo3", "campo3"),
new Foo("campoxx", "campoy") };
//Unimos los dos arreglos.
List foo3 = foo.Union(foo2);
foreach (Foo item in foo3)
{
System.Diagnostics.Debug.WriteLine(
item.Campo1 +"," + item.Campo2);
}
}
}
Devolvera:
"campo1","campo22"
"campo3","campo3"
"campox","campoy"
"campo11","campo22"
"campoxx","campoyy"
Si nos damos cuenta Union, compara el contenido de todo el objeto y devuelve un arreglo con los objetos diferentes.
Si desearamos comparar únicamente ciertos campos, por ejemplo en nuestra clase queremos devolver los objetos que tengan relación únicamente con el campo2:
Debemos tener algo como: (comparación foo.Campo2=foo2.Campo2).
campo1, campo22
campo3,campo3
campox,campoy
Al intentar realizar esto, intente usar algún tipo de lambda expression, pero sorpresa el parámetro Union solo acepta dos sobrecargas de objetos :
public static IEnumerable Union(
this IEnumerable first,
IEnumerable second,
IEqualityComparer comparer
)
Si nos fijamos en la segunda sobrecarga, nos pide un objeto de tipo IEqualityComparer, leyendo la documentación de Microsoft, esta interfaz nos permite declarar una clase para personalizar la comparación del comando Union.
Creamos la clase FooComparer para personalizar la comparación, de nuestros arreglos unicamente con el campo2.
class
FooComparer : IEqualityComparer<Foo>
{
public bool Equals(Foo x,
Foo y)
{
if
(!Object.ReferenceEquals(x, null) &&
!object.ReferenceEquals(y,
null)) //&&
!Object.ReferenceEquals(x,y)
{
return
x.Campo2.ToUpper() == y.Campo2.ToUpper();
}
return false;
}
public int GetHashCode(Foo
obj)
{
if
(ReferenceEquals(obj, null)) return 0;
int
hashCampo2 = objCampo2.GetHashCode();
//int hashCampo1 = objCampo1.GetHashCode();
return hashCampo2; //^ hashCampo1 ;
}
}
Lo importante esta en el codigo Hash calculado, si quisieramos comparar otros campos del objeto, habrá que calcular el hash para estos campos y devolver algo como campo a codeHash1 ^ codeHash2, etc.
Para probar nuestra clase:
List foo3 = foo.Union(foo2, new FooComparer());
Devolverá:
campo1, campo22
campo3,campo3
Comentarios
Publicar un comentario