Domanda

Ecco cosa sto cercando di fare. Sto interrogando un file XML usando LINQ to XML, il che mi dà un < T > oggetto, dove T è il mio "villaggio" classe, riempita con i risultati di questa query. Alcuni risultati sono duplicati, quindi vorrei eseguire un Distinct () sull'oggetto IEnumerable, in questo modo:

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);
    }
}

Poiché il comparatore predefinito non funzionava per l'oggetto Village, ne ho implementato uno personalizzato, come mostrato qui nella classe 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
}

Il metodo Distinct () non funziona, poiché ho esattamente lo stesso numero di risultati con o senza di esso. Un'altra cosa, e non so se di solito è possibile, ma non posso entrare in AllianceComparer.Equals () per vedere quale potrebbe essere il problema.
Ho trovato esempi di questo su Internet, ma non riesco a far funzionare la mia implementazione.

Speriamo che qualcuno qui possa vedere cosa potrebbe esserci di sbagliato qui! Grazie in anticipo!

È stato utile?

Soluzione

Il problema è con il tuo GetHashCode . Dovresti modificarlo per restituire invece il codice hash di AllianceName .

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

Il fatto è che se Equals restituisce true , gli oggetti dovrebbero avere lo stesso codice hash che non è il caso di diversi oggetti Village con lo stesso AllianceName . Dato che Distinct funziona costruendo internamente una tabella hash, finirai con oggetti uguali che non saranno affatto abbinati a causa di diversi codici hash.

Allo stesso modo, per confrontare due file, se l'hash di due file non è lo stesso, non è necessario controllare i file stessi. saranno diversi. Altrimenti, continuerai a controllare per vedere se sono davvero uguali o meno. Questo è esattamente ciò che si comporta la tabella hash che Distinct utilizza.

Altri suggerimenti

  

restituisce alleanze.Seleziona (v = > v.AllianceName) .Distinct ();

Ciò restituirebbe un IEnumerable < string > anziché IEnumerable < Village > .

O cambia la linea

return alliances.Distinct(new AllianceComparer());

a

return alliances.Select(v => v.AllianceName).Distinct();
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top