Почему не важно, что Null не безопасен для тех, кто любит безопасность типов - PullRequest
3 голосов
/ 27 декабря 2011

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

Такие языки, как C #, серьезно относятся к безопасности типов, они статически типизированы, а дженерики в C # значительно безопаснее типов, чем шаблоны C ++. Даже ArrayList, который считается не таким безопасным, как List<>, поскольку он List<object> гораздо более безопасен, чем, например, List<dynamic>, что, я думаю, должно быть возможным, но, безусловно, неясно.

Однако мне интересно, снова используя C # в качестве примера, почему все еще null. Мне нравится и одобряет null, но он не соответствует безопасности типов остальной части языка.

Возможно, в некоторых отношениях 'null' улучшает производительность, предотвращая создание всего, что требуется по умолчанию, но также требует дополнительной трудоемкой проверки во время выполнения, чтобы компьютер выдавал нулевые исключения и тому подобное.

String s = null;
int n = s.Length; // error like a type error, even if technically it isn't

Ответы [ 2 ]

9 голосов
/ 27 декабря 2011

На самом деле я не слишком увлекаюсь концепцией безопасности типов

Может быть, вам следует.

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

Я не думаю, что нужен , чтобы быть безопасным типом, хотя это, безусловно, помогает.Многие люди пишут код на C ++, языке, который имеет относительно слабую безопасность типов (потому что указатели могут быть преобразованы в и из произвольных целых чисел).Тем не менее, C ++ также является языком, который был разработан, чтобы поощрять повторное использование кода через надежный код, инкапсулированный в классы.

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

Такие языки, как C #, серьезно относятся к безопасности типов

Действительно.

Обобщения в C # значительно более безопасны по сравнению с шаблонами C ++.

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

Даже ArrayList, который считается не таким типобезопасным, как List<T>, потому что это List<object>, гораздо более безопасен, чем, например, List<dynamic>, что, я думаю, должно быть возможным, но, безусловно, вполне возможнонеясный.

Ну, динамика - это интересный случай.Как я уже говорил ранее, динамический в основном означает «переместить проверку типа этой вещи во время выполнения».

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

Вы правы, чтобы поднять эту проблему;нулевые значения создают сложную проблему при проверке типов.Хотелось бы, чтобы статически типизированный язык был «безопасным для памяти», чтобы гарантировать, что ни один недопустимый битовый шаблон никогда не попадет в переменную, аннотируемую конкретным типом.C # (за пределами небезопасного подмножества) достигает этой цели , за исключением того, что нулевой эталонный битовый шаблон со всеми нулями всегда допустим в переменной, аннотированной ссылочным типом, даже если этот битовый шаблон ссылается на недопустимый объект.

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

Исторические причины.Нулевые ссылки очень полезны, несмотря на их опасность, и C # выходит из давней традиции языков программирования, которые допускают нулевые ссылки.

Лично я предпочел бы, чтобы мы включили обнуляемость в структуру с первого дня, чтобы вы могли иметь типы значений, допускающие значение NULL или NULL, а также ссылочные типы NULL или NULL.Помните, что в следующий раз, когда вы разрабатываете систему типов с нуля.

также требует дополнительной трудоемкой проверки времени выполнения для компьютера, чтобы выдавать нулевые исключения, и такие

Этона самом деле не так уж и плохо.Обычно эти вещи реализуются, когда страница виртуальной памяти, содержащая нулевой указатель, помечается как недоступная для чтения, записи или выполнения.Попытка сделать это приводит к исключению, вызванному оборудованием.И даже в тех случаях, когда вам нужно выполнить нулевую проверку, сравнение регистра с нулем довольно быстрое.

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

Небезопасная ковариация массива также проблематична; это истинная проблема с системой типов. Мы должны делать проверки типов каждый раз, когда вы записываете элемент более производного типа в массив его базового типа. Это мой кандидат на «худшую особенность» CLR.

4 голосов
/ 27 декабря 2011

NULL означает отсутствие экземпляра, ничего. Как таковой, он не может иметь тип, и поэтому вы не можете проверять типы на NULL.

Потребность в NULL приходит со ссылками: по крайней мере, при создании объектов со ссылками они должны указывать на «ничто». И NULL делает именно это.

...