Я хочу иметь метод Расширения "равно" между 2-байтовыми массивами - PullRequest
1 голос
/ 28 июня 2009

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

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

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

Ответы [ 3 ]

7 голосов
/ 28 июня 2009

Вы, конечно, не можете перегружать операторы методами расширения. Причина, по которой он не работает для метода 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;
}
6 голосов
/ 24 июня 2010
using System.Linq;

byte[] a = {1,2,3}; 
byte[] b = {1,2,3}; 
bool same = a.SequenceEqual(b);
0 голосов
/ 13 июля 2010

Я сделал это для той же цели:

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). В моем конкретном случае у меня есть только простые типы значений

...