Pregunta

Esto es lo que intento hacer. Estoy consultando un archivo XML usando LINQ to XML, lo que me da un IEnumerable < T > objeto, donde T es mi "Pueblo" clase, llena con los resultados de esta consulta. Algunos resultados están duplicados, por lo que me gustaría realizar un 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 ingresar a 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 de antemano!

¿Fue útil?

Solución

El problema es con su GetHashCode . Debería modificarlo para que devuelva el código hash de AllianceName en su lugar.

int IEqualityComparer<Village>.GetHashCode(Village obj)
{
    return obj.AllianceName.GetHashCode();
}

La cuestión es que si Equals devuelve true , los objetos deben tener el mismo código hash, que no es el caso para diferentes objetos Village con el mismo AllianceName . Dado que Distinct funciona construyendo una tabla hash internamente, terminará con objetos iguales que no coincidirán en absoluto debido a los diferentes códigos hash.

Del mismo modo, para comparar dos archivos, si el hash de dos archivos no es el mismo, no es necesario que compruebe los archivos. serán diferentes. De lo contrario, continuará verificando si son realmente iguales o no. Eso es exactamente lo que se comporta en la tabla hash que Distinct utiliza.

Otros consejos

  

devolver alianzas. Seleccione (v = > v.AllianceName) .Distinct ();

Eso devolvería un IEnumerable < string > en lugar de IEnumerable < Village > .

O cambia la línea

return alliances.Distinct(new AllianceComparer());

a

return alliances.Select(v => v.AllianceName).Distinct();
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top