Значения модуля в F # не инициализируются.Зачем? - PullRequest
13 голосов
/ 09 июля 2011

Я получил странное поведение, когда использовал F #.Когда я использую let связывания в модуле, и если значение создается из конструктора, то оно неинициализируется при использовании снаружи.(Я использовал его из C #, используя ModuleName.s2 или ModuleName.f ())

//in a module
let s1 = "1" //normal
let s2 = new String('i', 5) //null

let f () =
    s2.Equals("something") //Exception

Это нормальное поведение?Заранее спасибо.

РЕДАКТИРОВАТЬ: В целях отладки я хочу скомпилировать его как исполняемый файл.Это может быть проблемой, как отмечали другие люди.

Ответы [ 2 ]

16 голосов
/ 09 июля 2011

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

UPDATE

Брайан указал мне на эту часть спецификации , что указывает на то, что это ожидаемое поведение.

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

[<EntryPoint>]
let main _ =
    0

Затем вы можете вызвать этот основной метод из своего приложения C #, чтобы убедиться, что содержимое модуля правильно инициализировано.

ОБНОВЛЕНИЕ 2

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

5 голосов
/ 09 июля 2011

По какой-то причине SomeModule.s2 реализовано как свойство (только для чтения), которое возвращает значение невыразимого статического поля <StartupCode$FS>.$Program.s2@9.Если вы компилируете как приложение, это поле инициализируется в основном методе.При использовании из кода C # этот метод не вызывается, поэтому поле не инициализируется.

Если вы компилируете как библиотеку, код такой же, за исключением того, что поле инициализируется в статическом конструкторе$Program класс, поэтому он должен работать при использовании из C #.

Причина, по которой s1 всегда работает, заключается в оптимизации: компилятор F # понимает, что это константа, и реализует f() как "1".Equals("something").

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