Объект C# не является несуществующим, но (myObject! = пустой указатель), все еще возвращают false

Зачем вам писать такой сценарий? Поскольку вы находитесь в своей тестовой среде, вы можете контролировать, присутствует ли значение или нет. Наличие / отсутствие этого значения свидетельствует о некотором предыдущем поведении. Итак, у вас есть два сценария

Scenario: Something has happened and the value is present
Scenario: Something has NOT happened the the value is absent

В первом сценарии вы можете сделать дополнительные проверки, и если что-то пройдет, вы знаете, что все в порядке. Во втором сценарии вы знаете, что вам не нужно делать дополнительные проверки, чтобы вы могли сделать что-то другое.

Вы никогда не хотите, чтобы сценарии проходили, когда они должны терпеть неудачу. Если вам нужен какой-то оператор IF в вашем сценарии, вам нужен рефакторинг и извлечение дополнительных сценариев.

18
задан Patrick Desjardins 30 September 2008 в 22:54
поделиться

7 ответов

== и/или! = оператор, перегруженный для класса объекта региона?

Теперь, когда Вы отправили код для перегрузок:

перегрузки должны, вероятно, быть похожими на следующее (код, взятый от регистраций, сделанных Jon Skeet и Philip Rieck ):

public static bool operator ==(Region r1, Region r2)
{
    if (object.ReferenceEquals( r1, r2)) {
        // handles if both are null as well as object identity
        return true;
    }

    if ((object)r1 == null || (object)r2 == null)
    {
       return false;
    }        

    return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id);
}

public static bool operator !=(Region r1, Region r2)
{
    return !(r1 == r2);
}
29
ответ дан 30 November 2019 в 06:07
поделиться

Те перегрузки оператора повреждаются.

Во-первых, это делает жизнь намного легче если! = реализован, просто звоня == и инвертируя результат.

, Во-вторых, перед регистрациями ничтожности == должен быть:

if (object.ReferenceEquals(r1, r2))
{
    return true;
}
16
ответ дан 30 November 2019 в 06:07
поделиться

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

3
ответ дан 30 November 2019 в 06:07
поделиться

Обе из перегрузок неправильные

 public static bool operator ==(Region r1, Region r2)
    {
        if (object.ReferenceEquals(r1, null))
        {
            return false;
        }
        if (object.ReferenceEquals(r2, null))
        {
            return false;
        }

        return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id);
    }

, если r1 И r2 являются пустыми, первый тест ( объект. ReferenceEquals (r1, пустой указатель) ), возвратит false, даже при том, что r2 является также пустым.

попытка

//ifs expanded a bit for readability
 public static bool operator ==(Region r1, Region r2)
    {
        if( (object)r1 == null && (object)r2 == null)
        {
           return true;
        }
        if( (object)r1 == null || (object)r2 == null)
        {
           return false;
        }        
        //btw - a quick shortcut here is also object.ReferenceEquals(r1, r2)

        return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id);
    }
7
ответ дан 30 November 2019 в 06:07
поделиться

Так это, что эти проверки здесь не являются правильными:

public static bool operator !=(Region r1, Region r2)
{
    if (object.ReferenceEquals(r1, null))
    {
        return false;
    }
    if (object.ReferenceEquals(r2, null))
    {
        return false;
    }
...
0
ответ дан 30 November 2019 в 06:07
поделиться

Существует другая возможность, что необходимо нажать значок обновления рядом с параметром, который Вы наблюдаете. Попытка VS не отставать от производительности, не оценивая каждый оператор/параметр. Смотрите для проверки, прежде чем Вы начнете вносить изменения в места, это не релевантно.

0
ответ дан 30 November 2019 в 06:07
поделиться

Для сравнения на равенство типа "T" перегрузите эти методы:

int GetHashCode() //Overrides Object.GetHashCode
bool Equals(object other) //Overrides Object.Equals; would correspond to IEquatable, if such an interface existed
bool Equals(T other) //Implements IEquatable<T>; do this for each T you want to compare to
static bool operator ==(T x, T y)
static bool operator !=(T x, T y)

Ваш код сравнения для конкретного типа должен выполняться в одном месте : типобезопасный IEquatable метод интерфейса Равен (T прочее) . Если вы сравниваете с другим типом (T2), реализуйте также IEquatable и поместите код сравнения полей для этого типа в Equals (T2 other).

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

bool Equals(object other)
{
    if (other is T) //replicate this for each IEquatable<T2>, IEquatable<T3>, etc. you may implement
        return Equals( (T)other) ); //forward to IEquatable<T> implementation
    return false; //other is null or cannot be compared to this instance; therefore it is not equal
}

bool Equals(T other)
{
    if ((object)other == null) //cast to object for reference equality comparison, or use object.ReferenceEquals
        return false;
    //if ((object)other == this) //possible performance boost, ONLY if object instance is frequently compared to itself! otherwise it's just an extra useless check
        //return true;
    return field1.Equals( other.field1 ) &&
           field2.Equals( other.field2 ); //compare type fields to determine equality
}

public static bool operator ==( T x, T y )
{
    if ((object)x != null) //cast to object for reference equality comparison, or use object.ReferenceEquals
        return x.Equals( y ); //forward to type-safe Equals on non-null instance x
    if ((object)y != null)
        return false; //x was null, y is not null
    return true; //both null
}

public static bool operator !=( T x, T y )
{
    if ((object)x != null)
        return !x.Equals( y ); //forward to type-safe Equals on non-null instance x
    if ((object)y != null)
        return true; //x was null, y is not null
    return false; //both null
}

Обсуждение:

Предыдущая реализация централизует сравнение конкретного типа (то есть равенство полей) до конца реализации IEquatable для типа. Операторы == и ! = имеют параллельную, но противоположную реализацию. Я предпочитаю это тому, чтобы иметь одну ссылку на другую, чтобы для зависимого был дополнительный вызов метода. Если оператор ! = просто вызовет оператор == , а не предложит оператор с одинаково высокой эффективностью, то вы можете просто использовать ! (Obj1 == obj2) и избегайте дополнительного вызова метода. Сравнение с самим собой не учитывается оператором equals и реализациями IEquatable , поскольку в некоторых случаях он может создавать 1. ненужные издержки и / или 2. несовместимую производительность в зависимости от того, как часто экземпляр сравнивается с самим собой по сравнению с другими экземплярами.

Альтернатива, которую я не люблю, но должен упомянуть, состоит в том, чтобы отменить эту настройку, вместо этого централизовать код равенства для конкретного типа в операторе равенства и иметь методы Equals, зависящие от который. Затем можно использовать ярлык ReferenceEquals (obj1, obj2) , чтобы проверять равенство ссылок и нулевое равенство одновременно, как Филипп упоминал в предыдущем посте, но эта идея вводит в заблуждение. Кажется, ты убиваешь двух зайцев одним выстрелом, но вы на самом деле создаете больше работы - после определения, что объекты не являются ни нулевыми, ни одинаковыми экземплярами, вам, кроме того, ДОЛЖНО быть проверено, является ли каждый экземпляр нулевым. В моей реализации вы проверяете, является ли единичный экземпляр пустым ровно один раз. К тому времени, когда вызывается метод экземпляра Equals, уже исключено, что первый сравниваемый объект является нулевым, поэтому остается только проверить, является ли другой нулевым. Таким образом, после не более чем двух сравнений мы переходим непосредственно к проверке поля, независимо от того, какой метод мы используем ( Equals (объект), Equals (T), ==,! = ). Кроме того, как я уже говорил, если вы действительно сравниваете и возражаете против себя большую часть времени, то вы можете добавить эту проверку в метод Equals непосредственно перед погружением в сравнения полей.

2
ответ дан 30 November 2019 в 06:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: