Compare duas listas que contêm muitos objetos (2ª parte)
-
14-11-2019 - |
Pergunta
Referindo-me à pergunta que fiz anteriormente:Compare duas listas que contêm muitos objetos
É impressionante ver o quão rápida essa comparação é feita com a implementação da interface IEqualityComparer: exemplo aqui
Como mencionei na minha outra pergunta, esta comparação me ajuda a fazer backup de uma pasta de origem em uma pasta de destino.Sei que quero sincronizar com pastas, portanto preciso comparar as datas dos arquivos.Sempre que faço algo como:
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;
}
}
Seria bom se eu pudesse fazer algo semelhante usando sinais de maior ou igual.Também tentei usar a propriedade tick e não funcionou.Talvez eu esteja fazendo algo errado.Acredito que não seja possível comparar as coisas com o sinal de menor que igual implementando esta interface.Além disso, não entendo como funciona esta classe;Só sei que é impressionante a rapidez com que ele percorre toda a lista.
Solução
Como os objetos DateTime são diferentes no caso em que um DateTime é menor que o outro, você obtém códigos hash diferentes para os objetos é e d e o método Equals não é chamado.Para que a comparação das datas funcione, você deve remover a parte da data do método GetHashCode:
public int GetHashCode(MyFile a)
{
int rt = ((a.compareName.GetHashCode() * 251 + a.size.GetHashCode())
* 251 + a.deepness.GetHashCode()) *251;
return rt;
}
Outras dicas
Toda a sua abordagem é fundamentalmente falha porque o seu IEqualityComparer.Equals
método não é simétrico.Isso significa Equals(file1, file2)
não é igual Equals(file2, file1)
por causa da maneira como você está usando o operador menor que.
A documentação:
afirma claramente:
Notas para Implementadores
O método Equals é reflexivo, simétrico e transitivo.Ou seja, retorna verdadeiro se for usado para comparar um objeto consigo mesmo;verdadeiro para dois objetos x e y se for verdadeiro para y e x;e verdadeiro para dois objetos x e z se for verdadeiro para x e y e também verdadeiro para y e z.
Implementações são necessárias para garantir que, se o método Equals retornar verdadeiro para dois objetos x e y, o valor retornado pelo método GetHashCode para x deverá ser igual ao valor retornado para y.
Em vez disso, você precisa usar o IComparable
interface ou IEqualityComparer
em combinação com comparações de datas.Do contrário, as coisas podem parecer funcionar por um tempo, mas você se arrependerá mais tarde.
Seu GetHashCode tem um problema:
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;
}
Alterei a parte da data porque também precisava do tempo, portanto, uso a propriedade ticks.Eu me livrei do código hash dateModified e funciona muito bem.aqui está como modifiquei meu programa.Eu estava tendo problemas para comparar as datas, portanto usei a propriedade 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;
}
}
Ainda não sei como funciona essa função de código hash.O bom é que funciona muito bem.