Подтвердить что ты не робот

Почему короткое замыкание не исключает MissingMethodException, связанное с недостижимой ветвью логического AND (&&)?

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

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

4b9b3361

Ответ 1

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

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

Метод CameraPresent1() даже не запускается.

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

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

Ответ 2

С# Specification раздел 7.12

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

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

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

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


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

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

<ч/" > Edit:

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

Ответ 3

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

Ответ 4

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

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