2016-12-28 12 views
7

내가 선언 한 초기화하지이 같은 튜플 :F 번호의 튜플은 결코

module MyModule = 
    let private INVALID_TUPLE = ("0", DateTime.MinValue) 

나는 그것이 모듈에, 항상 널 (null)의 낮은 참조 :

let private invalidForNone someOtherTuple = 
    match someOtherTuple with 
    | None -> INVALID_TUPLE // it's null 
    | Some(t) -> t 

또한, 나는 배치 할 때 튜플 선언의 중단 점은 절대로 안타.

스크립트 (fsx) 파일에서 똑같은 일을하면 디버깅을 시작하고 실행하십시오. 튜플 선언에서 중단 점이 발생하고 튜플에 대한 참조가 좋습니다.

내 모듈의 ILSpy는 INVALID_TUPLE을 만드는 Main 메서드가있는 일부 시작 코드가 생성되었음을 보여줍니다. 분명히, 그것은 웬일인지 달리지 않고있다?

다음은 동작을 재현하는 샘플입니다 (이제는 MSTest가 코드를 실행하는 방식과 관련이 있습니다). 이것을 C# 단위 테스트에서 호출하십시오. 결과는 null가됩니다. 사실 F # 코드의 중단 점은 전혀 실행되지 않습니다. 도서관에서를 참조하거나 단위 테스트 러너를 사용하여 - 예를 들어, 당신이 컴파일 된 실행 파일의 Main 방법을 실행하지 않는 방법으로 실행으로 컴파일 된 코드를 실행하면

module NullTupleTest 
open System 

let private INVALID_TUPLE = ("invalid", DateTime.MinValue) 

let private TupleTest someTuple = 
    match someTuple with 
    | None -> INVALID_TUPLE 
    | Some(dt) -> dt 

let Main = TupleTest None 
+0

null인지 어떻게 확인합니까? 실제로 어딘가에서 작동하지 않는 것이 있습니까? –

+0

글쎄요, NRE 다운 스트림을 얻었고, 디버거에서 그렇게 알려주기 때문에 null이라는 것도 압니다. – dudeNumber4

+0

디버거가 신뢰할 수 없습니다. 그것에 의지하지 마십시오. NRE를 얻을 수있는 곳과 null 값이 어떻게 될지 보여줄 수 있습니까? 아니면 또 다른 최소한의 재생산 가능한 예제를 제공합니까? 또한 "[질문하는 방법] (http://stackoverflow.com/help/how-to-ask)"을 참조하십시오. –

답변

7

오류가 발생할 수 있습니다. 솔루션은 F # 프로젝트를 라이브러리로 컴파일하고 다른 실행 파일을 엔트리 포인트로 가질 수 있습니다. (또는 let 전역 값이 바인딩되지 않도록 코드를 수정할 수도 있지만 첫 번째 방법을 선호합니다.)

이는 F # 컴파일러가 실행 파일로 컴파일 된 코드에 대해 다르게 초기화를 처리하고 라이브러리로 컴파일 된 코드

  • 라이브러리의 초기화 코드 필드는, 초기화 코드 Main 방법 놓여져 실행이 처음
  • 를 액세스 할 때 실행되는 정적 생성자에 넣고 그 때에 실행되고 응용 프로그램이 시작됩니다 (단, 정상적인 실행 파일로 시작될 때만).

이 이유는 F # 컴파일러가 초기화 순서를 유지하려고 시도하기 때문입니다 (위에서 아래로). 실행 파일의 경우 Main 메서드에서 이니셜 라이저를 실행하여 수행 할 수 있습니다. 라이브러리의 경우 안정적인 방법이 없기 때문에 (라이브러리에 "초기화"가 없기 때문에) 정적 생성자를 사용하는 것이 가장 좋은 방법입니다.