0

このクラスには比較子があります

public partial class CityCountryID :IEqualityComparer<CityCountryID>
{

    public string City { get; set; }
    public string CountryId { get; set; }

    public bool Equals(CityCountryID left, CityCountryID right)
    {
        if ((object)left == null && (object)right == null)
        {
            return true;
        }
        if ((object)left == null || (object)right == null)
        {
            return false;
        }
        return left.City.Trim().TrimEnd('\r', '\n') == right.City.Trim().TrimEnd('\r', '\n') 
            && left.CountryId == right.CountryId;
    }

    public int GetHashCode(CityCountryID obj)
    {
        return (obj.City + obj.CountryId).GetHashCode();
    }
}

Hashset と Distinct を使用してみましたが、どちらも機能していません。リストが大きすぎてeverrrrrrrには大きすぎたため、dbでこれを実行したくありませんでした。これが c# で機能しないのはなぜですか? ユニークな国、都市のリストを取得したい。

            List<CityCountryID> CityList = LoadData("GetCityList").ToList();
            //var unique = new HashSet<CityCountryID>(CityList);
            Console.WriteLine("Loading Completed/ Checking Duplicates");
            List<CityCountryID> unique = CityList.Distinct().ToList();
4

2 に答える 2

5

あなたEqualsGetHashCode方法は一貫していません。ではEquals都市名を削除していますが、 ではそうでGetHashCodeはありません。これは、2 つの等しい値が異なるハッシュ コードを持つ可能性があることを意味し、通常の契約に違反します。

それが最初に修正することです。健全性のためにデータベース自体の都市名をトリミングしてから、チェックでTrim操作を削除することをお勧めします。Equalityそれは物事をずっと簡単にします。

2 つ目は、データベースで時間がかかっていた理由の解明です。特に 2 つのフィールドにインデックスがある場合は、ローカルよりもデータベースでパフォーマンスが向上することを強く期待しています。

次は、可能であれば型を不変にすることを検討することです。オブジェクトの変更可能なプロパティが等価性に影響を与えることを許可することは、一般的には悪い考えです。オブジェクトをディクショナリのキーとして使用した後 (または に追加した後) に、オブジェクトの等値依存プロパティを変更するとHashSet、まったく同じ参照を使用しても、再度取得できない場合があります。

編集:また、スコットが指摘したように、等値比較を実行するために を渡す、通常のメソッドとメソッドをオーバーライドする必要があります。現時点では、この 2 つの中間に位置しています ( を実装していますが、コンストラクターまたはコンストラクターへの引数として比較子を実際に提供していません)。一般に、型がそれ自体のために実装することはまれです。基本的に、型に「自然な」等価チェックを実装するか、型実装するスタンドアロンの等価チェックを実装します。実装する必要はありません-通常をオーバーライドするだけですIEqualityComparerEqualsGetHashCodeIEqualityComparer<T>DistinctHashSetIEqualityComparerIEqualityComparer<T>IEquatable<T>Equals(object)メソッドは機能しますが、一般的にIEquatable<T>は同時に実装することをお勧めします。

余談ですが、文字列連結を使用せずにハッシュ コードを計算することもお勧めします。例えば:

public override int GetHashCode()
{
    int hash = 17;
    hash = hash * 31 + CountryId.GetHashCode();
    hash = hash * 31 + City.GetHashCode();
    return hash;
}
于 2013-09-08T16:28:54.807 に答える
3

インターフェイスを実装する必要はIEquatable<T>ありませんでしIEqualityComparer<T>た (ドキュメント、特に「実装者への注意事項」セクションを必ず読んでください!)。IEqualityComparer は、クラスに組み込まれている既定のもの以外のカスタム比較子を使用する場合です。

また、ジョンGetHashCodeが一致しないことについて言及した変更を加える必要がありますEquals

于 2013-09-08T16:29:18.247 に答える