多くのオブジェクトを含む 2 つのリストを比較する (第 2 部)
-
14-11-2019 - |
質問
以前に尋ねた質問を参照してください:多数のオブジェクトを含む 2 つのリストを比較する
IEqualityComparer インターフェイスを実装することにより、比較がどれほど高速に行われるかを見るのは印象的です。 ここの例
他の質問で述べたように、この比較は、コピー元フォルダーをコピー先フォルダーにバックアップするのに役立ちます。フォルダーに同期したいので、ファイルの日付を比較する必要があることがわかります。私が次のようなことをするときはいつも:
public class MyFileComparer2 : IEqualityComparer<MyFile>
{
public bool Equals(MyFile s, MyFile d)
{
return
s.compareName.Equals(d.compareName) &&
s.size == d.size &&
s.deepness == d.deepness &&
s.dateModified.Date <= d.dateModified.Date; // This line does not work.
// I also tried comparing the strings by converting it to a string and it does
// not work. It does not give me an error but it does not seem to include the files
// where s.dateModified.Date < d.dateModified.Date
}
public int GetHashCode(MyFile a)
{
int rt = (a.compareName.GetHashCode() * 251 + a.size.GetHashCode() * 251 + a.deepness.GetHashCode() + a.dateModified.Date.GetHashCode());
return rt;
}
}
大なり記号または等号を使用して同様のことができれば素晴らしいでしょう。また、tickプロパティを使用してみましたが、機能しません。もしかしたら私は何か間違ったことをしているのかもしれません。このインターフェースを実装した不等号を使用して比較することはできないと思います。さらに、このクラスがどのように機能するのか理解できません。リスト全体を反復処理する速度が印象的であることだけはわかります。
解決
一方の DateTime が他方の DateTime より小さい場合、DateTime オブジェクトは異なるため、オブジェクトの異なるハッシュコードが取得されます。 s そして d Equals メソッドは呼び出されません。日付の比較を機能させるには、GetHashCode メソッドから日付部分を削除する必要があります。
public int GetHashCode(MyFile a)
{
int rt = ((a.compareName.GetHashCode() * 251 + a.size.GetHashCode())
* 251 + a.deepness.GetHashCode()) *251;
return rt;
}
他のヒント
あなたのアプローチ全体には根本的に欠陥があります。 IEqualityComparer.Equals
メソッドは対称ではありません。これはつまり Equals(file1, file2)
等しくない Equals(file2, file1)
小なり演算子の使用方法が原因です。
ドキュメント:
明確に次のように述べています。
実装者へのメモ
Equals メソッドは再帰的、対称的、推移的です。つまり、オブジェクトをそれ自体と比較するために使用される場合は true を返します。y と x に true の場合、2 つのオブジェクト x および y に対して true。x と y に当てはまり、y と z にも当てはまれば、2 つのオブジェクト x と z にも当てはまります。
実装では、Equals メソッドが 2 つのオブジェクト x および y に対して true を返す場合、x に対して GetHashCode メソッドによって返される値が y に対して返される値と等しくなるようにする必要があります。
代わりに、 IComparable
インターフェイスまたは IEqualityComparer
日付比較と組み合わせて使用します。そうしないと、一時的にはうまくいくように見えても、後で後悔することになります。
GetHashCode には問題があります:
public int GetHashCode(MyFile a)
{
int rt = (((a.compareName.GetHashCode() * 251)
+ a.size.GetHashCode() * 251)
+ a.deepness.GetHashCode() *251)
+ a.dateModified.Date.GetHashCode();
return rt;
}
時間も必要だったので、日付部分を変更しました。そのため、代わりに Nicks プロパティを使用します。dateModified ハッシュ コードを削除したところ、うまく機能しました。これがプログラムを変更した方法です。日付の比較に問題があったため、Ticks プロパティを使用しました。
public class MyFileComparer2 : IEqualityComparer<MyFile>
{
public bool Equals(MyFile s, MyFile d)
{
return
s.compareName.Equals(d.compareName) &&
s.size == d.size &&
s.deepness == d.deepness &&
//s.dateModified.Date <= d.dateModified.Date &&
s.dateModified.Ticks >= d.dateModified.Ticks
;
}
public int GetHashCode(MyFile a)
{
int rt = (((a.compareName.GetHashCode() * 251)
+ a.size.GetHashCode() * 251)
+ a.deepness.GetHashCode() * 251)
//+ a.dateModified.Ticks.GetHashCode();
;
return rt;
}
}
このハッシュコード関数がどのように機能するかはまだわかりません。良い点は、それがうまく機能することです。