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

Почему Java и С# не имеют неявных преобразований в boolean?

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

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

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

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

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

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

4b9b3361

Ответ 1

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

int x = ...;

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

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

Ответ 2

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

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

if( x = 5 ) { ... }

вместо:

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

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

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

Теперь, в С#, вы все равно можете создавать неявные операторы преобразования в 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

Ответ 3

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

Ответ 4

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

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

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

Ответ 5

Неявное преобразование любого значения int (например, (flags и 0x80)) в boolean подразумевает языковое заданное сопоставление от значения int к логическому. C сделал это и вызвал огромное количество путаницы и много ошибок программиста. Нет никакой веской причины, по которой значение null int всегда означает true (или false) и множество веских причин, по которым вы, возможно, захотите оставить решение программисту. По этим причинам неявное преобразование в boolean было отменено большинством современных языков.

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

Ответ 6

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

Ответ 7

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

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

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

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

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