Почему короткое замыкание не исключает 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
только потому, что оба они являются свойством (на уровне языка)?
Есть ли что-то еще, что объясняет разницу в поведении?
Ответы
Ответ 1
Второй член не оценивается.
Первый член не оценивается.
Метод CameraPresent1()
даже не запускается.
Когда вы вызываете CameraPresent1()
в первый раз, среда выполнения должна JIT-компилировать MSIL в собственный код. Это требует разрешения всех вызовов методов, даже тех, которые могут быть достигнуты только условно. Ошибка компиляции с MissingMethodException
.
С CameraPresent2()
вызов getter из CameraEnabled
компилируется только при первом вызове CameraE()
, что никогда не происходит.
Ответ 2
Операторы &&
и ||
называются условными логическими операторами. Они также называются "короткозамкнутыми" логическими операторами.
Операторы &&
и ||
являются условными версиями 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);
}