Eu quero ter um método de extensão “iguais” entre 2 matrizes de bytes
-
20-08-2019 - |
Pergunta
Estou fazendo algumas byte [] comparações.
Eu tentei == mas isso é apenas como a base é igual, que:
byte[] a = {1,2,3};
byte[] b = {1,2,3};
bool equals = a == b; //false
equals = a.Equals(b); //false
Eu tentei adicionar um método de extensão, mas desde que a classe base sobrecarregado Igual leva os mesmos argumentos, ele vai para o método base, em vez da extensão, se houver qualquer maneira eu posso usar um é igual a extensão (wthout mudá-la de nome. ..) ou (melhor ainda) uso == operador?
Aqui está o que eu realmente tenho que comparar:
public static bool ContentEquals(this byte[] array, byte[] bytes)
{
if (array == null || bytes == null) throw new ArgumentNullException();
if( array.Length != bytes.Length) return false;
for (int i = 0; i < array.Length; i++)
if (array[i] != bytes[i]) return false;
return true;
}
Solução
using System.Linq;
byte[] a = {1,2,3};
byte[] b = {1,2,3};
bool same = a.SequenceEqual(b);
Outras dicas
Você certamente não pode fazer sobrecarga de operadores com os métodos de extensão. O motivo ele não funciona para o método Equals
é que se qualquer método é aplicável sem o uso de métodos de extensão, esse método será escolhido antes de métodos de extensão são ainda examinadas.
Mesmo que o seu método Equals
é "melhor" em termos de converter os tipos de argumentos para os tipos de parâmetros formais, o compilador prefere sempre métodos "normais". Você vai ter que dar o seu método um nome diferente.
No entanto, você sempre pode usar o método Enumerable.SequenceEquals
. Eu não acredito que um curto-circuito a verificação de comprimento embora (mesmo que pudesse, para implementações ICollection<T>
). Você sempre pode implementar uma versão mais eficiente-se embora. De fato, se você acabou de mudar a sua implementação matriz existente para ser chamado SequenceEquals
ou mesmo ArrayEquals
, que seria ótimo:
public static bool ArrayEquals(this byte[] array, byte[] bytes)
{
// I'd personally use braces in all of this, but it's your call
if (array.Length != bytes.Length) return false;
for (int i = 0; i < array.Length; i++)
if (array[i] != bytes[i]) return false;
return true;
}
Note que seria muito bom para torná-lo genérico, mas que certamente custar um pouco de desempenho como a comparação não pode ser embutido:
public static bool ArrayEquals<T>(this T[] first, T[] second)
{
// Reference equality and nullity checks for safety and efficiency
if (first == second)
{
return true;
}
if (first == null || second == null)
{
return false;
}
if (first.Length != second.Length)
{
return false;
}
EqualityComparer<T> comparer = EqualityComparer<T>.Default;
for (int i = 0; i < first.Length; i++)
{
if (!comparer.Equals(first[i], second[i]))
{
return false;
}
}
return true;
}
Eu fiz isso para o mesmo fim:
static class Global
{
public static bool ArraysAreEqual(Array arr1, Array arr2)
{
if (arr1.Length != arr2.Length)
return false;
System.Collections.IEnumerator e1 = arr1.GetEnumerator();
System.Collections.IEnumerator e2 = arr2.GetEnumerator();
while(e1.MoveNext() && e2.MoveNext())
{
if(!e1.Current.Equals(e2.Current))
return false;
}
return true;
}
}
Mas note que os .Equals () pode até retornar falso em referência tipos quando eles são iguais (I não fez o teste, mas você pode tentar com StringBuilder). No meu caso particular só tenho simples de valor tipos