Почему Java и C # не имеют неявных преобразований в логические значения? - PullRequest
27 голосов
/ 01 июня 2010

С тех пор как я запустил Java, для меня было очень обидно, что он не поддерживает неявные преобразования числовых типов в логические, поэтому вы не можете делать такие вещи, как:

if (flags & 0x80) { ... }

вместо этого вы должны пройти через это безумие:

if ((flags & 0x80) != 0) { ... }

То же самое с нулем и объектами. Любой другой C-подобный язык, который я знаю, включая JavaScript, позволяет это, поэтому я думал, что Java была просто дебильной, но я только что обнаружил, что C # такой же (по крайней мере, для чисел, не знаю о null / objects): http://msdn.microsoft.com/en-us/library/c8f5xwh7(VS.71).aspx

Microsoft специально изменила его с C ++, так почему? Я явно что-то упускаю. Зачем менять (что я считал) самой естественной вещью в мире, чтобы заставить ее печатать дольше? Что на земле не так с этим?

Ответы [ 7 ]

37 голосов
/ 01 июня 2010

Для наглядности. Это делает следующую ошибку просто незаконной:

int x = ...;

if (x = 0)  // in C: assign 0 to x and always evaluate to false 
   ....     // never executed

Примечание: большинство современных компиляторов C / C ++ выдают предупреждение (но не ошибку) по этому простому шаблону, но возможны многие варианты. Это может подкрасться к тебе.

32 голосов
/ 01 июня 2010

В Java и C # отказались от неявных преобразований в логические значения , чтобы уменьшить вероятность ошибки программиста .

Например, многие программисты случайно написали бы:

if( x = 5 ) { ... }

вместо:

if( x == 5 ) { ... }

Что, конечно, приводит к совершенно другому поведению, поскольку первый оператор выполняет присваивание (что всегда приводит к истине), а второй выполняет сравнение. В прошлом разработчики иногда писали такие задания в обратном порядке, чтобы избежать ловушки, поскольку:

if( 5 = x ) { ... } // doesn't compile.

Теперь в C # вы все еще можете создавать неявные операторы преобразования в bool для своих собственных типов - хотя это редко рекомендуется, поскольку большинство разработчиков этого не ожидают:

public class MyValue
{
   public int Value { get; set; }

   public static implicit operator bool( MyValue mb )
   {
       return mb.Value != 0;
   }
}

MyValue x = new MyValue() { Value = 10; }
if( x ) { ... } // perfectly legal, compiler applies implicit conversion
10 голосов
/ 01 июня 2010

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

8 голосов
/ 01 июня 2010

Вы получили это назад.
Это на самом деле C, который не поддерживает boolean, поэтому if (и любое другое условное выражение) фактически ожидает значение int, а не boolean. Тогда значение int 0 обрабатывается как false, а любое другое значение обрабатывается как true.

Некоторые люди действительно находят это немного двусмысленным, потому что этот тип поведения может привести ко многим ошибкам, как указывали другие. Из-за этого разработчики Java отказались от поддержки только boolean типов в выражениях условия. И когда Microsoft решила внедрить MS-Java (AKA C #), они позаимствовали этот принцип проектирования.

Если вам это не нравится, вы можете программировать на разных языках, которые не имеют этого ограничения.

6 голосов
/ 01 июня 2010

Неявное преобразование любого значения int (например, (flags & 0x80)) в логическое значение подразумевает отображение, определенное языком, из значения int в логическое значение. Си сделал это и вызвал огромное количество путаницы и много ошибок программиста. Нет веских причин, по которым нулевое значение типа int ВСЕГДА означает истина (или ложь), и множество веских причин, по которым вы можете оставить решение на усмотрение программиста. По этим причинам неявное преобразование в логическое значение было прекращено большинством современных языков.

Если вводить семь дополнительных символов каждый раз, когда вы проводите небольшой тест, значит «безумие», вы можете быть не в той профессии. Если вы выполняете битовые тесты в int очень часто, вы можете подумать о том, преждевременно ли вы оптимизируете для экономии памяти.

3 голосов
/ 01 июня 2010

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

2 голосов
/ 01 июня 2010

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

То, что Java делает любое принуждение, для вас удобно и нарушает модель строгой типизации.

Отображение всего диапазона целых чисел - или даже большего диапазона чисел с плавающей точкой - на два логических значения чревато несогласием по поводу произвольного присвоения «истинности» и «ложности».

  • Какие значения отображаются на false и true? Если вы C, только ноль отображается на false, а все остальные значения - true. Если вы оболочка bash, она перевернута.
  • Как должны отображаться отрицательные значения?

Когда вы пытаетесь автоматически преобразовать double в целое число, Java помечает это как ошибку «потери точности». По аналогии, преобразование числа в логическое значение также должно привести к потере точности. Вместо этого Java решила не поддерживать его синтаксически.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...