Являются ли ссылки необнуляемыми по умолчанию в F #? - PullRequest
5 голосов
/ 07 марта 2011

Я знаю, что в C # это не так, и это в таких языках, как Haskell (если я не ошибаюсь), поэтому подумал, что, возможно, F # также имеет ту же семантику по умолчанию.

Также, хотя этоне существует в C #, это ограничение языка, а не время выполнения, верно?Как и F #, так и какой-либо другой новый язык .NET могут фактически реализовать это как значение по умолчанию без использования какого-либо взлома.

Ответы [ 2 ]

11 голосов
/ 07 марта 2011

В F #, если вы определяете новый класс или другой тип в коде F #, то он будет по умолчанию не обнуляемым в том смысле, что, например,

type MyClass() = ...
...
let x : MyClass = null   // does not compile

Однако он компилируется в код .NET IL как класс, который является ссылочным типом в .NET, который может иметь значение null, и, следовательно, либо C # может создавать пустые значения этого типа, либо даже в F #

let x : MyClass = Unchecked.defaultOf<MyClass>

даст вам ноль. Таким образом, в этом смысле, это очень «ограничение времени выполнения» - вы никогда не сможете создать язык .NET, который может «представить класс в C # так, чтобы он выглядел как нормальный класс», а также «гарантировать, что экземпляры этот тип никогда не бывает нулевым ". Таким образом, вы всегда должны принимать прагматичные решения здесь. F # пытается предотвратить несчастные случаи и раздражение, связанные с нулем, когда вы остаетесь внутри F #, но если вы имеете дело с деталями взаимодействия или среды выполнения .NET, в конце дня null всегда остается без ответа. (Ошибка в миллиард долларов.)

5 голосов
/ 08 марта 2011

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

[<AllowNullLiteral>]
type T1() = class end

type T2() = class end

let t1 : T1 = null
let t2 : T2 = null // compiler error

EDIT

Что касается вашего дополнительного вопроса, да, этот атрибут относится к самому типу. В подавляющем большинстве типов F # этот атрибут не применяется; если у вас есть функция или метод с параметром, для которого вы хотите, чтобы у вас было допустимое значение типа или «нулевое» значение дозорного, то вы должны использовать option тип:

let myFunc (o:option<T2>) = 
  match o with
  | None -> "No value passed in"
  | Some(t2) -> "A T2 instance was passed in"

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

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