C# Assert.AreNotEqual против Equals

Пытаясь убедиться в том, что C# Equals для IEnumerables является ссылкой equals, я обнаружил кое-что странное. Со следующей настройкой в ​​NUnit

var a = (IEnumerable<string>)(new[] { "one", "two" });
var b = (IEnumerable<string>)(new[] { "one", "two" });

этот тест

Assert.IsFalse(a.Equals(b));

проходит, пока этот тест

Assert.AreNotEqual(a, b);

нет. Кто-нибудь может объяснить, почему?

Редактировать: Спасибо за ответы. Я только что прочитал документацию для NUnit, и там говорится то же самое, что AreEqual и AreNotEqual с проверками коллекций на равенство каждого элемента коллекции. Думаю, я застрял в идее, что AreEqual и AreNotEqual просто используют простые Equals.


person Boris    schedule 25.04.2009    source источник


Ответы (2)


Вызов a.Equals(b) возвращает false, потому что a и b не являются одними и теми же объектами (хотя они, конечно, являются идентичными перечислениями). Метод Equals, если он не переопределен, автоматически сравнивает объекты по их ссылке, что и происходит в данном случае.

Assert.AreNotEqual немного умнее этого. Он предназначен для целей отладки, в отличие от метода Equals, поэтому фактически сравнивает последовательности, полученные двумя перечислениями, поскольку распознает IEnumerable<T> как особый тип. Вы также должны заметить, что он делает и другие интересные вещи, например, возвращает true, когда два параметра численно идентичны, но имеют разные типы значений (например, short и long).

Надеюсь, это поможет.

person Noldorin    schedule 25.04.2009

Я не смотрел исходный код NUnit, чтобы увидеть, как ребята из NUnit написали код AreNotEqual. Однако я могу рассказать вам, как это делается для MbUnit, который имеет такое же поведение.

Сначала в AssertNotEqual(a, b) проверяется равенство ссылок, выполняя такой код:

    if (Object.ReferenceEquals(left, right))
        return true;

В вашем случае не получится. Затем он проверяет, относятся ли объекты к типу IEnumerable. Если они есть, повторите их и сравните, одинаковы ли элементы и в том же порядке.

Однако тип T в IEnumerable сложнее, чем string или ValueType в MbUnit. AssertNotEqaual(a, b) не будет ошибкой.

    var a = (IEnumerable<StringBuilder>)(new[] { new StringBuilder("one"), new StringBuilder("two") });
    var b = (IEnumerable<StringBuilder>)(new[] { new StringBuilder("one"), new StringBuilder("two") });

    Assert.IsFalse(a.Equals(b));  // Success
    Assert.AreNotEqual(a, b);     // Success
person Vadim    schedule 25.04.2009