Почему «ноль» присутствует в C # и Java? - PullRequest
71 голосов
/ 07 октября 2008

Мы заметили, что множество ошибок в нашем программном обеспечении, разработанном в C # (или Java), вызывают исключение NullReferenceException.

Есть ли причина, по которой слово "null" даже включено в язык?

В конце концов, если бы не было "null", у меня не было бы ошибки, верно?

Другими словами, какая функция в языке не может работать без нуля?

Ответы [ 25 ]

90 голосов
/ 07 октября 2008

Андерс Хейлсберг, "C # папа", только что говорил об этом в своем интервью в Computerworld :

Например, в системе типов у нас нет разделения между значениями и ссылочными типами и обнуляемостью типов. Это может показаться немного странным или немного техническим, но в C # ссылочные типы могут быть нулевыми, например, строки, но типы значений не могут быть пустыми. Было бы неплохо иметь ссылочные типы, не допускающие значения NULL, поэтому вы можете объявить, что «эта строка никогда не может быть нулевой, и я хочу, чтобы ваш компилятор проверил, что я никогда не смогу указывать здесь нулевой указатель».

50% ошибок, с которыми люди сталкиваются сегодня, кодируют с помощью C # на нашей платформе, и то же самое относится и к Java в этом отношении, вероятно, являются нулевыми ссылочными исключениями. Если бы у нас была более сильная система типов, которая позволила бы вам сказать, что «этот параметр никогда не может быть нулевым, и вы, компилятор, проверяете это при каждом вызове, выполняя статический анализ кода». Тогда мы могли бы удалить классы ошибок.

Сайрус Наджмабади, бывший инженер-разработчик программного обеспечения в команде C # (сейчас работает в Google), обсуждает эту тему в своем блоге: ( 1st , 2nd , 3rd , , 4 ). Кажется, что самым большим препятствием для принятия ненулевых типов является то, что нотация нарушит привычки программистов и кодовую базу. Примерно 70% ссылок на программы на C # могут в конечном итоге стать ненулевыми.

Если вы действительно хотите иметь необнуляемый ссылочный тип в C #, попробуйте использовать Spec # который является расширением C #, что позволяет использовать "!" как ненулевой знак.

static string AcceptNotNullObject(object! s)
{
    return s.ToString();
}
29 голосов
/ 07 октября 2008

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

Как бы вы предложили убрать понятие недействительности?

20 голосов
/ 28 января 2009

Как и многие вещи в объектно-ориентированном программировании, все это восходит к ALGOL. Тони Хоар только что назвал это "ошибкой в ​​миллиард долларов". Если что, это преуменьшение.

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

16 голосов
/ 07 октября 2008

Нуль в C # - это, в основном, перенос из C ++, в котором были указатели, которые ничего не указывали в памяти (или, скорее, адрес 0x00). В этом интервью Андерс Хейлсберг говорит, что он хотел бы добавить ненулевые ссылочные типы в C #.

Ноль также имеет законное место в системе типов, однако, что-то вроде нижнего типа (где object - тип top ). В lisp нижний тип - NIL, а в Scala - Nothing.

Было бы возможно спроектировать C # без каких-либо нулей, но тогда вам пришлось бы придумать приемлемое решение для обычного использования, обычно используемого для null, например unitialized-value, not-found, default-value, undefined-value и None<T>. Вероятно, было бы меньше принятия среди программистов на C ++ и Java, если бы они все равно преуспели в этом. По крайней мере до тех пор, пока они не увидели, что программы на C # никогда не имели исключений нулевого указателя.

13 голосов
/ 07 октября 2008

Удаление нуля не решит многое. Вы должны иметь ссылку по умолчанию для большинства переменных, которая установлена ​​в init. Вместо исключений с нулевой ссылкой вы получите неожиданное поведение, потому что переменная указывает на неправильные объекты. По крайней мере, нулевые ссылки быстро терпят неудачу, а не вызывают неожиданное поведение.

Вы можете посмотреть на шаблон нулевого объекта для решения части этой проблемы

12 голосов
/ 07 октября 2008

В конце концов, если бы не было «null», у меня не было бы ошибки, верно?

Ответ НЕТ . Проблема не в том, что C # допускает null, проблема в том, что у вас есть ошибки, которые проявляются в исключении NullReferenceException. Как уже говорилось, в языке есть нулевые значения для указания либо «пустого» ссылочного типа, либо ненулевого значения (пусто / ничего / неизвестно).

12 голосов
/ 07 октября 2008

Ноль - чрезвычайно мощная функция. Что вы делаете, если у вас есть отсутствие значения? Это NULL!

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

Я предпочитаю ноль, поскольку для меня это более верный признак того, что это на самом деле. Если я не могу получить сущность из своего слоя постоянства, я хочу ноль. Я не хочу пустого значения. Но это я.

Это особенно удобно с примитивами. Например, если у меня есть истина или ложь, но это используется в форме безопасности, где разрешение может быть Разрешить, Запретить или не задано. Ну, я хочу, чтобы это значение не было нулевым. Так я могу использовать bool?

Я мог бы рассказать о гораздо большем, но я оставлю это там.

5 голосов
/ 07 октября 2008

Вопрос может быть интерпретирован как «лучше ли иметь значение по умолчанию для каждого типа ссылки (например, String.Empty) или ноль?». В этом предположении я предпочел бы иметь нулевые значения, потому что;

  • Я не хотел бы писать по умолчанию конструктор для каждого класса, который я пишу.
  • Я бы не хотел ненужного память для такого размещения значения по умолчанию.
  • Проверка, является ли ссылка нулевая, скорее дешевле чем сравнение значений.
  • Это очень можно иметь больше ошибок, которые труднее обнаружить, а не NullReferanceExceptions. Это хорошо бы иметь такое исключение что ясно указывает на то, что я делать (предполагая) что-то не так.
5 голосов
/ 07 октября 2008

Null не вызывает NullPointerExceptions ...

Программисты вызывают исключения NullPointerException.

Без нулей мы вернулись к использованию фактического произвольного значения, чтобы определить, что возвращаемое значение функции или метода было недопустимым. Вам все еще нужно проверить наличие возвращенного -1 (или чего-либо еще), удаление нулей не решит магически лень, а лишь запутает его.

3 голосов
/ 07 октября 2008

Если вы получаете исключение NullReferenceException, возможно, вы продолжаете ссылаться на объекты, которых больше не существует. Это не проблема с 'null', это проблема с вашим кодом, указывающим на несуществующие адреса.

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