Что такое безопасный тип?

Что означает "безопасный тип"?

Ответ 1

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

Несколько простых примеров:

// Fails, Trying to put an integer in a string
String one = 1;
// Also fails.
int foo = "bar";

Это также относится к аргументам метода, поскольку вы передаете им явные типы:

int AddTwoNumbers(int a, int b)
{
    return a + b;
}

Если я попытался вызвать это, используя:

int Sum = AddTwoNumbers(5, "5");

Компилятор выкинет ошибку, потому что я передаю строку ( "5" ), и она ожидает целое число.

В свободно типизированном языке, таком как javascript, я могу сделать следующее:

function AddTwoNumbers(a, b)
{
    return a + b;
}

если я назову его так:

Sum = AddTwoNumbers(5, "5");

Javascript автоматически преобразует 5 в строку и возвращает "55". Это связано с javascript, используя знак + для конкатенации строк. Чтобы сделать это с учетом типа, вам нужно сделать что-то вроде:

function AddTwoNumbers(a, b)
{
    return Number(a) + Number(b);
}

Или, возможно:

function AddOnlyTwoNumbers(a, b)
{
    if (isNaN(a) || isNaN(b))
        return false;
    return Number(a) + Number(b);
}

если я назову его так:

Sum = AddTwoNumbers(5, " dogs");

Javascript автоматически преобразует 5 в строку и добавляет их, чтобы вернуть "5 собак".

Не все динамические языки так же прощайте, как javascript (на самом деле динамический язык не подразумевает подразумеваемый свободный язык (см. Python)), некоторые из них фактически дадут вам ошибку времени выполнения при недействительном типе.

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

Теперь вернемся к С#...

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

 public class Foo : Bar
 {
 }

Здесь я создал новый класс (Foo), который подклассы Bar. Теперь я могу создать метод:

 void DoSomething(Bar myBar)

И вызывать его, используя либо Foo, либо Bar в качестве аргумента, оба будут работать, не вызывая ошибки. Это работает, потому что С# знает, что любой дочерний класс Bar реализует интерфейс Bar.

Однако вы не можете сделать обратное:

void DoSomething(Foo myFoo)

В этой ситуации я не могу передать Bar этому методу, потому что компилятор не знает, что Bar реализует интерфейс Foo. Это связано с тем, что дочерний класс может (и обычно будет) сильно отличаться от родительского класса.

Конечно, теперь я ушел с глубокого конца и вышел за рамки оригинального вопроса, но все его хорошие вещи, чтобы знать:)

Ответ 2

Нельзя путать тип-безопасность со статическим/динамическим типированием или сильным/слабым типом.

Язык с типом безопасности - это тот, где единственными операциями, которые можно выполнить на данных, являются те, которые допускаются типом данных. То есть, если ваши данные имеют тип X и X не поддерживают операцию y, тогда язык не позволит вам выполнить y(X).

Это определение не устанавливает правила при проверке. Это может быть во время компиляции (статическая типизация) или во время выполнения (динамическая типизация), как правило, через исключения. Это может быть немного: некоторые статически типизированные языки позволяют вам вводить данные из одного типа в другой, а действительность отбросов должна проверяться во время выполнения (представьте, что вы пытаетесь применить Object к Consumer - компилятор не знает, приемлемо это или нет).

Тип безопасности не обязательно означает строго типизированный, либо - некоторые языки, как известно, слабо типизированы, но все же, возможно, печатаются безопасно. Возьмите Javascript, например: его система типа настолько слаба, насколько они приходят, но все еще строго определена. Он позволяет автоматическое литье данных (например, строки в int), но в пределах четко определенных правил. Насколько я знаю, ни один случай, когда программа Javascript будет вести себя как мода undefined, и если вы достаточно умны (я не уверен), вы должны быть в состоянии предсказать, что произойдет при чтении кода Javascript.

Примером типа небезопасного языка программирования является C: чтение/запись значения массива вне границ массива имеет поведение undefined по спецификации. Невозможно предсказать, что произойдет. C - это язык, который имеет систему типов, но не безопасен по типу.

Ответ 3

Многие ответы здесь объединяют безопасность типов со статической типизацией и динамической типизацией. Динамически типизированный язык (например, smalltalk) также может быть безопасным для типов.

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

Ответ 4

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

Есть 2 основных вопроса, связанных с безопасностью типов. Память ** и тип данных (с соответствующими операциями).

Объем памяти**

Для char обычно требуется 1 байт на символ или 8 бит (зависит от языка, в Java и С# хранятся символы юникода, для которых требуется 16 бит). Для int требуется 4 байта или 32 бита (обычно).

Визуально:

char: |-|-|-|-|-|-|-|-|

int: |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|

Безопасный для типов язык не позволяет вставлять int в char во время выполнения (это должно привести к исключению из класса или из-за нехватки памяти). Однако на небезопасном языке типа вы перезаписываете существующие данные еще на 3 смежных байта памяти.

int >> char:

|-|-|-|-|-|-|-|-| |?|?|?|?|?|?|?|?| |?|?|?|?|?|?|?|?| |?|?|?|?|?|?|?|?|

В приведенном выше случае 3 байта справа перезаписываются, поэтому любые указатели на эту память (скажем, 3 последовательных символа), которые ожидают получить предсказуемое значение символа, теперь будут иметь мусор. Это вызывает undefined поведение в вашей программе (или, что еще хуже, возможно, в других программах, в зависимости от того, как ОС выделяет память - очень маловероятно в наши дни).

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

Тип данных

Более тонкий и прямой тип проблемы заключается в том, что два типа данных используют одинаковое распределение памяти. Возьмите int против неподписанного int. Оба 32-битные. (Точно так же легко могут быть char [4] и int, но более распространенной проблемой является uint vs. int).

|-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|

|-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|

Небезопасный язык типов позволяет программисту ссылаться на правильно распределенный диапазон из 32 битов, но когда значение беззнакового целого читается в пространстве целого (или наоборот), мы снова имеем undefined поведение. Представьте себе проблемы, которые это может вызвать в банковской программе:

"Чувак! Я переиграл 30 долларов, и теперь у меня осталось 65 506 долларов !!"

... Конечно, банковские программы используют гораздо большие типы данных. ;) ЛОЛ!

Как уже отмечали другие, следующая проблема - вычислительные операции над типами. Это уже достаточно покрыто.

Скорость против безопасности

Большинству программистов сегодня не нужно беспокоиться о таких вещах, если они не используют что-то вроде C или C++. Оба этих языка позволяют программистам легко нарушать безопасность типов во время выполнения (прямое обращение к памяти), несмотря на все усилия компиляторов минимизировать риск. ОДНАКО, это не все плохо.

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

Ответ 5

Объяснение от крупного либерального искусства, а не основного специалиста:

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

Например, в С# я определяю функцию как:

 void foo(int arg)

Затем компилятор остановит меня от этого:

  // call foo
  foo("hello world")

В других языках компилятор не остановит меня (или нет компилятора...), поэтому строка будет передана логике, а затем, вероятно, произойдет что-то плохое.

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

Внизу, с типом безопасных языков, когда у вас есть строка типа "123", и вы хотите работать с ней, как int, вам нужно написать больше кода для преобразования строки в int или когда вы имеют int like 123 и хотят использовать его в сообщении типа "Ответ 123", вам нужно написать больше кода для преобразования/перевода его в строку.

Ответ 6

Язык программирования, который является "безопасным по типу", означает следующие вещи:

  • Вы не можете читать из неинициализированных переменных
  • Вы не можете индексировать массивы за пределами своих границ
  • Вы не можете выполнять сброс непроверенных типов

Ответ 7

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

На практике это означает, что 7 (целочисленный тип) отличается от "7" (цитируемый символ строкового типа).

PHP, Javascript и другие динамические языки сценариев обычно слабо типизированы, поскольку они будут преобразовывать (строку) "7" в (целое число) 7, если вы попытаетесь добавить "7" + 3, хотя иногда у вас есть для этого явно (и Javascript использует символ "+" для конкатенации).

C/С++/Java не поймет этого, иначе он объединяет результат в "73". Тип-безопасность предотвращает эти типы ошибок в коде, делая требование типа явно.

Тип-безопасность очень полезна. Решение вышеизложенного "7" + 3 было бы типом cast (int) "7" + 3 (равно 10).

Ответ 8

Чтобы лучше понять, смотрите видео ниже, которое демонстрирует код на безопасном языке типа (С#) и НЕ набирает безопасный язык (javascript).

http://www.youtube.com/watch?v=Rlw_njQhkxw

Теперь для длинного текста.

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

Например, JavaScript не является типом безопасного языка. В приведенном ниже коде "num" есть числовая переменная, а "str" - строка. Javascript позволяет мне делать "num + str", теперь GUESS будет выполнять арифметику или конкатенацию.

Теперь для приведенного ниже кода результаты равны "55", но важным моментом является путаница в создании какой операции он будет делать.

Это происходит потому, что javascript не является безопасным для типа языком. Это позволяет устанавливать один тип данных на другой тип без ограничений.

<script>
var num = 5; // numeric
var str = "5"; // string
var z = num + str; // arthimetic or concat ????
alert(z); // displays  "55"
</script>

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

enter image description here

Ответ 9

Попробуйте это объяснение...

TypeSafe означает, что переменные статически проверяются для соответствующего назначения во время компиляции. Например, скопируйте строку или целое число. Эти два разных типа данных не могут быть перекрестно назначены (т.е. Вы не можете назначить целое число в строку и не можете назначить строку целому числу).

Для поведения, отличного от типов, рассмотрите следующее:

object x = 89;
int y;

если вы попытаетесь сделать это:

y = x;

компилятор выдает ошибку, в которой говорится, что он не может преобразовать объект System.Object в Integer. Вам нужно сделать это явно. Один из способов:

y = Convert.ToInt32( x );

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

Нестандартные коллекции изобилуют ASP.NET(например, коллекции приложений, сеансов и представлений). Хорошая новость об этих коллекциях заключается в том, что (сводя к минимуму несколько соображений управления состоянием сервера) вы можете разместить практически любой тип данных в любой из трех коллекций. Плохая новость: потому что эти коллекции не являются типичными, вам нужно будет присвоить значения соответствующим образом при их возврате.

Например:

Session[ "x" ] = 34;

работает отлично. Но для назначения целочисленного значения обратно вам нужно:

int i = Convert.ToInt32( Session[ "x" ] );

Читайте о дженериках, которые помогут вам легко реализовать коллекции типов.

С# является типичным языком, но смотрите статьи о С# 4.0; интересные динамические возможности маяков (хорошо ли, что С# по существу получает опцию Strict: Off... мы увидим).

Ответ 10

Type-Safe - это код, который обращается к только адресам памяти, к которым разрешен доступ, и только с четко определенными, допустимыми способами. Код типа безопасный не может выполнять операцию над объектом, который является недопустимым для этого объекта. Компиляторы языка С# и VB.NET всегда создают безопасный для текста код, который, как проверяется, безопасен во время компиляции JIT.

Ответ 11

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

Для многих переменных набор значений, которые могут быть назначены переменной, определяется во время написания программы. Например, переменной, называемой "цвет", может быть разрешено принимать значения "красный", "зеленый" или "синий" и никогда никаких других значений. Для других переменных эти критерии могут меняться во время выполнения. Например, переменной, называемой "цвет", может быть разрешено принимать значения в столбце "name" таблицы "Цвета" в реляционной базе данных, где "красный", "зеленый" и "синий" являются тремя значениями для "name" в таблице "Colors", но какая-то другая часть компьютерной программы может быть добавлена ​​в этот список во время работы программы, и переменная может принимать новые значения после их добавления в таблицу цветов.

Многие типы безопасных языков дают иллюзию "безопасности типа", настаивая на строго определяющих типах переменных и позволяя только переменной присваивать значения одного и того же "типа". Существует несколько проблем с этим подходом. Например, программа может иметь переменную "yearOfBirth", которая является годом рождения человека, и возникает соблазн напечатать его как короткое целое. Однако это не краткое целое число. В этом году это число меньше 2009 года и превышает -10000. Однако этот набор растет с каждым годом, когда программа работает. Сделать это "короткий int" недостаточно. Что необходимо для обеспечения безопасности этой переменной - это функция проверки времени выполнения, которая гарантирует, что число всегда больше -10000 и меньше, чем в следующем календарном году. Нет компилятора, который может применять такие критерии, поскольку эти критерии всегда являются уникальными характеристиками проблемной области.

Языки, использующие динамическую типизацию (или утиную печать или отображение символов), такие как Perl, Python, Ruby, SQLite и Lua, не имеют понятия типизированных переменных. Это заставляет программиста писать процедуру проверки во время выполнения для каждой переменной, чтобы убедиться, что она верна, или переносить последствия необъяснимых исключений во время выполнения. По моему опыту, программисты в статически типизированных языках, таких как C, С++, Java и С#, часто убаюкивают мысль о том, что статически определенные типы - все, что им нужно сделать, чтобы получить преимущества безопасности типов. Это просто неверно для многих полезных компьютерных программ, и трудно предсказать, верно ли это для какой-либо конкретной компьютерной программы.

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

Ответ 12

Концепция:

Чтобы быть очень простым Type Safe как значения, он гарантирует, что тип переменной должен быть безопасным, как

  1. нет неправильного типа данных, например, невозможно сохранить или инициализировать переменную строкового типа с целым числом
  2. Внешние индексы не доступны
  3. Разрешить только определенную область памяти

так что все дело в безопасности типов вашего хранилища в терминах переменных.