О не допускающих NULL-значения дебатах типов

Есть небольшая проблема с вашей строкой даты. Это работает, когда 20181015 151706 изменяется только на часть даты 20181015.

SELECT CONVERT(DATETIME, col)
FROM (
   select '20181015' col
) t1
7
задан Ed Guiness 15 December 2009 в 14:59
поделиться

7 ответов

Я не понимаю Вашего примера. Если Ваш "= новый Класс ()" является просто заполнителем вместо не наличия пустого указателя, то это - (к моим глазам), очевидно, ошибка. Если это не, то реальная ошибка - то, что "..." не установил ее содержание правильно, который является точно тем же в обоих случаях.

Исключение, которое показывает Вам, что Вы забыли инициализировать c, скажет Вам в том, какая точка это не инициализируется, но не, где это должно было быть инициализировано. Точно так же пропущенный цикл (неявно) скажет Вам, где он должен был иметь ненулевой .count, но не, что должно было быть сделано или где. Я не вижу ни один, как являющийся немного легче на программисте.

Я не думаю, что точка "никакого аннулирует", должен просто сделать, текстовое находит и заменяет и делает их всех в пустые экземпляры. Это очевидно бесполезно. Точка должна структурировать Ваш код, таким образом, Ваши переменные никогда не находятся в состоянии, где они указывают на бесполезные/неправильные значения, из которых ПУСТОЙ УКАЗАТЕЛЬ просто наиболее распространен.

6
ответ дан 6 December 2019 в 09:22
поделиться

Я признаю, что действительно не читал много о Spec#, но я понял, что NonNullable был по существу атрибутом, что Вы ставите параметр, не обязательно на объявлении переменной; Превратите свой пример во что-то как:

class Class { ... }

void DoSomething(Class c)
{
    if (c == null) return;
    for(int i = 0; i < c.count; ++i) { ... }
}

void main() {
    Class c = nullptr;
    // ... ... ... code ...
    DoSomething(c);
}

С Spec# Вы отмечаете doSomething, чтобы сказать, что "параметр c не может быть пустым". Это походит на хорошую функцию, чтобы иметь мне, поскольку это означает, что мне не нужна первая строка в DoSomething () метод (который является легким для упущения строки, и абсолютно бессмысленный к контексту DoSomething ()).

2
ответ дан 6 December 2019 в 09:22
поделиться

Идея ненулевых типов состоит в том, чтобы позволить компилятору, а не клиенту находить ошибки. Предположим, вы добавили к своему языку два спецификатора типа @nullable (может быть null) и @nonnull (никогда не null) (я использую синтаксис аннотации Java).

Когда вы определяете функцию, вы аннотируете ее аргументы. Например, следующий код скомпилирует

int f(@nullable Foo foo) {
  if (foo == null) 
    return 0;
  return foo.size();
}

Даже если foo может иметь значение null на входе, поток управления гарантирует, что при вызове foo.size () foo не равен null.

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

Следующее также будет скомпилировано, потому что foo не равен null на входе:

int g(@nonnull Foo foo) {
  return foo.size(); // OK
}

Однако вы не сможете вызывать g с обнуляемым указателем:

@nullable Foo foo;
g(foo); // compiler error!

Компилятор выполняет анализ потока для каждой функции, поэтому он может определить, когда @nullable становится @nonnull (например, внутри оператора if, который проверяет наличие нуля). Он также примет достоверное определение @nonnull при условии, что оно будет немедленно инициализировано.

@nonnull Foo foo = new Foo();

По этой теме можно найти гораздо больше в моем блоге .

2
ответ дан 6 December 2019 в 09:22
поделиться

Поскольку я вижу его существует две области, где пустой указатель используется.

Первым является отсутствие значения. Например, булевская переменная может быть TRUE или FALSE, или пользователь еще не выбрал установку, следовательно пустой указатель. Это полезно и хорошая вещь, но возможно было реализовано неправильно первоначально и существует теперь попытка формализовать то использование. (Должна там быть вторая булевская переменная для содержания состояния набора/сброса или пустого указателя как часть логики с тремя состояниями?)

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

Так, какой из них интересуется Вы?

0
ответ дан 6 December 2019 в 09:22
поделиться

Мне нравится использование ПУСТОГО УКАЗАТЕЛЯ. Его некоторое время, так как я работал в C++, но он сделал очень легким найти мои проблемы относительно возвращаемых значений и ссылок и зафиксировать их.

-2
ответ дан 6 December 2019 в 09:22
поделиться

Сейчас я работаю над этой темой на C #. .NET имеет Nullable для типов значений, но обратная функция не существует для ссылочных типов.

Я создал NotNullable для ссылочных типов и переместил проблему из if (больше никаких проверок на null) в домен типов данных. Это заставляет приложение генерировать исключения во время выполнения, а не во время компиляции.

0
ответ дан 6 December 2019 в 09:22
поделиться

Немного странно, что ответ, помеченный как «ответ» в этой цепочке, в первую очередь подчеркивает проблему с нулевым значением, а именно:

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

Было бы неплохо, если бы компилятор мог улавливать подобные ошибки во время компиляции, а не во время выполнения?

Если вы использовали язык, подобный ML (SML, OCaml, SML и F # в некоторой степени) или Haskell ссылочные типы не допускают значения NULL. Вместо этого вы представляете «нулевое» значение, заключая его в тип параметра. Таким образом, вы фактически изменяете тип возвращаемого значения функции, если она может возвращать null в качестве допустимого значения. Итак, допустим, я хотел вытащить пользователя из базы данных:

let findUser username =
    let recordset = executeQuery("select * from users where username = @username")
    if recordset.getCount() > 0 then
        let user = initUser(recordset)
        Some(user)
    else
        None

Найти пользователя имеет тип val findUser: string -> user option , поэтому возвращаемый тип функции фактически говорит вам, что это может возвращать нулевое значение. Чтобы использовать код, вам необходимо обработать оба случая: Some и None:

match findUser "Juliet Thunderwitch" with
| Some x -> print_endline "Juliet exists in database"
| None -> print_endline "Juliet not in database"

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

Теперь мы видим проблему в примере кода OP:

class Class { ... }

void main() {
    Class c = new Class(); // set to new Class() by default
    // ... ... ... code ...
    for(int i = 0; i < c.count; ++i) { ... }
}

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

Теперь мы видим проблему в примере кода OP:

class Class { ... }

void main() {
    Class c = new Class(); // set to new Class() by default
    // ... ... ... code ...
    for(int i = 0; i < c.count; ++i) { ... }
}

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

Теперь мы видим проблему в примере кода OP:

class Class { ... }

void main() {
    Class c = new Class(); // set to new Class() by default
    // ... ... ... code ...
    for(int i = 0; i < c.count; ++i) { ... }
}

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

12
ответ дан 6 December 2019 в 09:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: