Странное поведение с условным оператором в .Net

Это поставило меня в тупик. Может быть, я слишком устал сейчас.

    Rectangle rectangle = new Rectangle(0, 0, image.Width, image.Height);
    Rectangle cropArea = inputArea == null ? rectangle : inputArea.Value;

    if (inputArea == null)
        cropArea = rectangle;

inputArea — это прямоугольник с нулевым значением, который в моем конкретном случае равен нулю.

Первые два оператора дают значение cropArea, инициализированное значением 0. Второе, однако, дает правильное значение cropArea на основе ширины и высоты изображения. Я что-то неправильно понял с условным оператором? Кажется, он не возвращает прямоугольник, когда inputArea = null? Есть ли какие-то особенности при работе с типами значений?

РЕДАКТИРОВАТЬ: Хорошо, я должен был сначала попробовать это: перезапустить VS. Кажется, отладчик солгал мне или что-то в этом роде. Во всяком случае, работает сейчас. Спасибо.


person Max    schedule 29.08.2010    source источник
comment
Я подумал о том, чтобы оставить это как подсказку всем остальным, что перезапуск VS всегда может решить неожиданные проблемы. Что вы думаете?   -  person Max    schedule 29.08.2010
comment
Кто, черт возьми, проголосовал за этот вопрос??? Это совершенно правильный вопрос, раскрывающий ужасную ошибку в Visual Studio.   -  person Darin Dimitrov    schedule 29.08.2010
comment
Кстати, обратите внимание, что здесь вы можете использовать оператор объединения null вместо условного оператора: croparea = inputArea ?? прямоугольник;   -  person Eric Lippert    schedule 29.08.2010


Ответы (5)


Это похоже на неприятную ошибку в режиме отладки Visual Studio, которая вас обманывает:

альтернативный текст

Теперь F10, чтобы перейти через эту строку, и вы получите:

альтернативный текст

На консоли печатаются правильные значения.

ВТФ.

person Darin Dimitrov    schedule 29.08.2010
comment
Вы пробовали Nullable‹Rectangle› - person Michael D. Irizarry; 29.08.2010
comment
@JeremySpouken, для какой переменной? - person Darin Dimitrov; 29.08.2010
comment
@JeremySpouken: это эквивалентно Rectangle?. - person Timwi; 29.08.2010
comment
Интересно. Я ввел тот же код в VS и получил правильные значения (как в режиме DEBUG, так и в режиме RELEASE)... - person Timwi; 29.08.2010
comment
@Timwi, какой точный номер версии используемой вами VS и ОС? Для меня это 10.0.30319.1 RTMRel работает на Windows 7 x64. - person Darin Dimitrov; 29.08.2010
comment
@HiTech Magic, вы понимаете, что означает тип, допускающий значение NULL, в .NET и какая польза от System.Nullable<T>? Судя по вашим комментариям, у меня сложилось впечатление, что это не так. Я бы рекомендовал вам прочитать соответствующий раздел документации: msdn.microsoft.com/ en-us/library/b3h38hb0.aspx - person Darin Dimitrov; 29.08.2010
comment
@Darin: То же самое здесь, но 32-битное — это может иметь значение. Спасибо за копание :) - person Timwi; 29.08.2010
comment
@кому не все равно: Совершенно верно. Это System.Windows.Shapes.Rectangle, который не имеет значения Nullable (т.е. Silverlight). Я постараюсь добавить много лайков и т. д., чтобы в будущем все не так бурно реагировали на мои комментарии :) - person Gone Coding; 29.08.2010
comment
@HiTech Magic, теперь это проясняет ситуацию :-) Кроме того, если бы вы прочитали вопрос более внимательно, вы бы заметили, что он использует inputArea.Value и в классе System.Windows.Shapes.Rectangle не определено свойство Value, а также конструктор, принимающий 4 целочисленных параметра. - person Darin Dimitrov; 29.08.2010

Итак, вы говорите, что когда inputArea равно null, без оператора if вы получаете прямоугольник, инициализированный чем-то другим, кроме размера изображения? Я только что попробовал запустить это, и это работает нормально. Убедитесь, что image имеет размер и что inputArea на самом деле null.

person Matti Virkkunen    schedule 29.08.2010
comment
Да, все это казалось очень странным, пока я не понял, что Visual Studio мне солгала. Смотрите мою правку. - person Max; 29.08.2010

Ваш код кажется правильным. Условное выражение (или условный оператор, или первоначально называвшееся тернарным оператором... теперь все довольны? :)) должно быть взаимозаменяемо с операторами if/else.

Rectangle cropArea = inputArea == null ? rectangle : inputArea.Value;

должно быть точно так же, как:

Rectangle cropArea;
if (inputArea == null)
{
    cropArea = rectangle;
}
else
{
    cropArea = inputArea.Value;
}

(на самом деле они должны генерировать один и тот же IL-код).

Проследите с помощью отладчика и посмотрите, не выскочит ли что-нибудь.

person Gone Coding    schedule 29.08.2010
comment
Пожалуйста, не называйте условный оператор «тернарным оператором». Я отредактировал ваш ответ, чтобы исправить это, надеюсь, вы не возражаете. - person Timwi; 29.08.2010
comment
@Timwi: Теперь вам также нужно пожаловаться на сайт jQuery. Они также называют это тернарным оператором (другой язык, тот же оператор) :) learn.jquery .com/javascript-101/условный-код - person Gone Coding; 15.05.2014

Что за черт?

Rectangle rectangle = ...;
Rectangle cropArea;
if (inputArea == null)
    cropArea = rectangle;
else
    cropArea = inputArea.Value;

if (inputArea == null)
    cropArea = rectangle;

Зачем второе если? Это полностью и полностью избыточно. Сценарий, в котором cropArea может по-прежнему иметь значение null или ноль, — это если inputArea.Value имеет значение null/zero, поскольку вы не проверяли это (только если inputArea имеет значение null).

person Puppy    schedule 29.08.2010

person    schedule
comment
Теперь, почему спам в моей ветке, ребята :) @Hitech Rectangle? область ввода = ноль; Nullable‹Rectangle› inputArea2 = null; @TimWi - теперь, почему отрицательный голос ... просто пытался помочь ОП? - person StuartLC; 29.08.2010
comment
+1, потому что я ошибся в вашем посте и начал небольшую флейм-войну. Оказывается, только класс Silverlight Rectange не допускает значения NULL. - person Gone Coding; 29.08.2010