residuo - C#Distinto en IEnumerable<T> con IEqualityComparer personalizado
operadores logicos c# ejemplos (3)
O cambia la línea
return alliances.Distinct(new AllianceComparer());
a
return alliances.Select(v => v.AllianceName).Distinct();
Esto es lo que estoy tratando de hacer. Estoy consultando un archivo XML usando LINQ to XML, que me da un objeto IEnumerable <T
>, donde T es mi clase "Village", llena con los resultados de esta consulta. Algunos resultados están duplicados, por lo que me gustaría realizar Distinct () en el objeto IEnumerable, así:
public IEnumerable<Village> GetAllAlliances()
{
try
{
IEnumerable<Village> alliances =
from alliance in xmlDoc.Elements("Village")
where alliance.Element("AllianceName").Value != String.Empty
orderby alliance.Element("AllianceName").Value
select new Village
{
AllianceName = alliance.Element("AllianceName").Value
};
// TODO: make it work...
return alliances.Distinct(new AllianceComparer());
}
catch (Exception ex)
{
throw new Exception("GetAllAlliances", ex);
}
}
Como el comparador predeterminado no funcionaría para el objeto Village, implementé uno personalizado, como se ve aquí en la clase AllianceComparer:
public class AllianceComparer : IEqualityComparer<Village>
{
#region IEqualityComparer<Village> Members
bool IEqualityComparer<Village>.Equals(Village x, Village y)
{
// Check whether the compared objects reference the same data.
if (Object.ReferenceEquals(x, y))
return true;
// Check whether any of the compared objects is null.
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
return false;
return x.AllianceName == y.AllianceName;
}
int IEqualityComparer<Village>.GetHashCode(Village obj)
{
return obj.GetHashCode();
}
#endregion
}
El método Distinct () no funciona, ya que tengo exactamente el mismo número de resultados con o sin él. Otra cosa, y no sé si generalmente es posible, pero no puedo entrar en AllianceComparer.Equals () para ver cuál podría ser el problema.
He encontrado ejemplos de esto en Internet, pero parece que no puedo hacer que mi implementación funcione.
¡Con suerte, alguien aquí podría ver lo que podría estar mal aquí! ¡Gracias por adelantado!
return alliances.Select(v => v.AllianceName).Distinct();
Eso devolvería una IEnumerable<string>
IEnumerable<Village>
lugar de IEnumerable<Village>
.
El problema es con tu GetHashCode
. Debería modificarlo para devolver el código hash de AllianceName
lugar.
int IEqualityComparer<Village>.GetHashCode(Village obj)
{
return obj.AllianceName.GetHashCode();
}
El caso es que si Equals
devuelve true
, los objetos deberían tener el mismo código hash, que no es el caso para los diferentes objetos Village
con el mismo AllianceName
. Como Distinct
funciona construyendo internamente una tabla hash, terminarás con objetos iguales que no se emparejarán en absoluto debido a diferentes códigos hash.
De manera similar, para comparar dos archivos, si el hash de dos archivos no es el mismo, no necesita verificar los archivos en sí mismos. Ellos serán diferentes. De lo contrario, continuará verificando si realmente son iguales o no. Eso es exactamente lo que se comporta la tabla hash que utiliza Distinct
.