Я хочу иметь метод расширения “Equals” между 2-байтовыми массивами

StackOverflow https://stackoverflow.com/questions/1054459

Вопрос

Я делаю несколько сравнений byte[].

Я пробовал == но это точно так же, как базовые значения, которые:

byte[] a = {1,2,3};
byte[] b = {1,2,3};
bool equals = a == b; //false
equals = a.Equals(b); //false

Я попытался добавить метод расширения, но поскольку перегруженный базовый класс Equals принимает те же аргументы, он переходит к базовому методу, а не к расширению, могу ли я в любом случае использовать расширение Equals (без изменения его имени ...) или (что еще лучше) использовать оператор ==?

Вот что мне на самом деле нужно сравнить:

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;
}
Это было полезно?

Решение

using System.Linq;

byte[] a = {1,2,3}; 
byte[] b = {1,2,3}; 
bool same = a.SequenceEqual(b);

Другие советы

Вы, конечно, не можете выполнять перегрузку оператора с помощью методов расширения.Причина, по которой это не работает для Equals метод заключается в том, что если Любой метод применим без использования методов расширения, этот метод будет выбран еще до того, как методы расширения будут даже рассмотрены.

Даже несмотря на то, что ваш Equals метод "лучше" с точки зрения преобразования типов аргументов в формальные типы параметров, компилятор всегда предпочитает "обычные" методы.Вам придется присвоить своему методу другое имя.

Однако вы всегда можете использовать Enumerable.SequenceEquals способ.Я не верю, что это приводит к короткому замыканию проверки длины (хотя это могло бы быть, для ICollection<T> реализации).Однако вы всегда можете самостоятельно внедрить более эффективную версию.Действительно, если вы просто измените существующую реализацию массива, которая будет вызвана SequenceEquals или даже ArrayEquals, это было бы прекрасно:

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

Обратите внимание, что было бы неплохо сделать его универсальным, но это, безусловно, немного снизило бы производительность, поскольку сравнение не могло быть встроено:

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

Я сделал это с той же целью:

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

но обратите внимание, что .Equals() может даже возвращать false для ссылочных типов, когда они равны (я не проводил тест, но вы можете попробовать с помощью StringBuilder ).В моем конкретном случае у меня есть только простые типы значений

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top