Почему короткое замыкание не предотвращает исключение MissingMethodException, связанное с недоступной ветвью логического И (&&)? - PullRequest
20 голосов
/ 08 марта 2011

Во время проверки, присутствует ли камера и включена ли она на моем мобильном устройстве с Windows, я столкнулся с чем-то, чего я не понимаю.

Код выглядит так:

    public static bool CameraP(){

        return Microsoft.WindowsMobile.Status.SystemState.CameraPresent;
    }

    public static bool CameraE()
    {
        return Microsoft.WindowsMobile.Status.SystemState.CameraEnabled;
    }

    public static bool CameraPresent1()
    {
        return Microsoft.WindowsMobile.Status.SystemState.CameraPresent
              && Microsoft.WindowsMobile.Status.SystemState.CameraEnabled;
    }

    public static bool CameraPresent2()
    {
        return CameraP() && CameraE();
    }

Когда я звоню CameraPresent2(), возвращается false (камеры нет). Но когда я вызываю CameraPresent1(), я получаю исключение MissingMethodException с комментарием «Не удалось найти метод: get_CameraEnabled Microsoft.WindowsMobile.Status.SystemState.»

Второй термин оценивается в CameraPresent1 только потому, что они оба являются свойством (на уровне языка)?

Есть ли что-нибудь еще, что объясняет разницу в поведении?

Ответы [ 4 ]

31 голосов
/ 08 марта 2011

Второй член не оценивается.

Первый член не оценивается.

Метод CameraPresent1() даже не начинает выполняться.

Когда вы вызываете CameraPresent1() в первый раз, среда выполнения должна JIT-компилировать MSIL в собственный код. Это требует разрешения всех вызовов методов, даже тех, которые могут быть достигнуты только условно. Сбой компиляции с MissingMethodException.

При CameraPresent2() вызов метода получения CameraEnabled компилируется только тогда, когда CameraE() вызывается впервые, что никогда не происходит.

10 голосов
/ 08 марта 2011

C # Спецификация раздел 7.12

Операторы && и || называются условными логическими операторами. Их также называют «короткозамкнутыми» логическими операторами.

Операторы && и || являются условными версиями & и | Операторы:

  • Операция x && y соответствует операции x & y, за исключением того, что y оценивается, только если x не false.

  • Операция x || y соответствует операции x | y, за исключением того, что y оценивается, только если x не true.

<ч /> То есть спецификация C # гарантирует, что CameraE() будет называться тогда и только тогда, когда CameraP() истинно.

Это может быть проблемой с агрессивной оптимизацией компилятора, и, следовательно, реальная программа, кажется, нарушает спецификацию языка ...

<ч /> Edit:

Можно ли установить точку останова и показать окно разборки, чтобы увидеть точный сгенерированный код?

5 голосов
/ 08 марта 2011

Просто дикая догадка, но возможно ли, что это проблема компиляции JIT? Когда вызывается CameraPresent1, пытается ли он сопоставить вызов Microsoft.WindowsMobile.Status.SystemState.CameraEnabled с базовым устройством? Поскольку он не может найти метод get_CameraEnabled, вся функция завершается с ошибкой MissingMethodException.

0 голосов
/ 08 марта 2011

Глядя на проблему, как сообщалось, кажется, что нет смысла. Две версии должны быть идентичны. Интересно, однако, если проблема здесь в том, что API камеры использует dynamic в некоторый момент, и он пытается найти оператор true() / false() / &. Это может убедить его переключиться на bool логику:

public static bool CameraPresent1()
{
    return ((bool)Microsoft.WindowsMobile.Status.SystemState.CameraPresent)
          && ((bool)Microsoft.WindowsMobile.Status.SystemState.CameraEnabled);
}
...