다음을 통해 공유


명시적 필드: val 키워드(F#)

val 키워드는 클래스 또는 구조체 형식의 필드를 초기화하지 않고 선언하는 데 사용됩니다. 이렇게 선언되는 필드를 명시적 필드라고 합니다. 다른 사용은 val 키워드는 함께에서 member 는 자동으로 구현 된 속성을 선언 하는 키워드. 자동으로 구현 된 속성에 대 한 자세한 내용은 속성(F#).

 val [ mutable ] [ access-modifier ] field-name : type-name

설명

클래스 또는 구조체 형식의 필드를 정의하는 일반적인 방법은 let 바인딩을 사용하는 것입니다. 그러나 let 바인딩은 반드시 클래스 생성자의 일부로 초기화해야 한다는 문제가 있습니다. 이와 같은 초기화는 경우에 따라 불가능하거나, 필요하지 않거나, 바람직하지 않은 것일 수 있습니다. 초기화되지 않은 필드가 필요하면 val 키워드를 사용할 수 있습니다.

명시적 필드는 정적이거나 정적이지 않을 수 있습니다. access-modifier는 public, private 또는 internal일 수 있습니다. 기본적으로 명시적 필드는 공용입니다. 클래스의 let 바인딩은 항상 전용이며 바로 이 점에서 차이가 있습니다.

기본 생성자가 있는 클래스 형식의 명시적 필드에는 DefaultValue 특성이 필요합니다. 이 특성은 필드가 0으로 초기화되는 것으로 지정합니다. 필드의 형식은 0 초기화를 지원해야 합니다. 0 초기화를 지원하는 형식은 다음 중 하나에 해당하는 형식입니다.

  • 0 값이 있는 기본 형식

  • null 값을 정상 값, 비정상 값 또는 값의 표현으로 지원하는 형식. 여기에는 클래스, 튜플, 레코드, 함수, 인터페이스, .NET 참조 형식, unit 형식 및 구별된 공용 구조체 형식이 포함됩니다.

  • .NET 값 형식

  • 해당 필드가 모두 기본 0 값을 지원하는 구조체

경고

참고 .NET Framework 네임 스페이스 System.ComponentModel 같은 이름을 가진 특성을 포함 합니다.이 특성에 대 한 내용은 DefaultValueAttribute.

다음 코드에서는 기본 생성자가 있는 클래스에 명시적 필드를 사용하는 방법을 보여 주고 이와 비교하기 위해 let 바인딩을 사용하는 방법도 보여 줍니다. let 바인딩된 필드 myInt1은 전용 필드입니다. let 바인딩된 필드 myInt1을 멤버 메서드에서 참조하는 경우 자체 식별자 this가 필요하지 않습니다. 그러나 명시적 필드 myInt2와 myString을 참조할 때는 자체 식별자가 필요합니다.

type MyType() =
    let mutable myInt1 = 10
    [<DefaultValue>] val mutable myInt2 : int
    [<DefaultValue>] val mutable myString : string
    member this.SetValsAndPrint( i: int, str: string) =
       myInt1 <- i
       this.myInt2 <- i + 1
       this.myString <- str
       printfn "%d %d %s" myInt1 (this.myInt2) (this.myString)

let myObject = new MyType()
myObject.SetValsAndPrint(11, "abc")
// The following line is not allowed because let bindings are private. 
// myObject.myInt1 <- 20
myObject.myInt2 <- 30
myObject.myString <- "def"

printfn "%d %s" (myObject.myInt2) (myObject.myString)

출력은 다음과 같습니다.

11 12 abc

30 def

다음 코드에서는 기본 생성자가 없는 클래스에 명시적 필드를 사용하는 방법을 보여 줍니다. 이 경우 DefaultValue 특성은 필요하지 않지만 형식에 대해 정의되는 생성자에서 모든 필드를 초기화해야 합니다.

type MyClass =
    val a : int
    val b : int
    // The following version of the constructor is an error 
    // because b is not initialized. 
    // new (a0, b0) = { a = a0; } 
    // The following version is acceptable because all fields are initialized. 
    new(a0, b0) = { a = a0; b = b0; }

let myClassObj = new MyClass(35, 22)
printfn "%d %d" (myClassObj.a) (myClassObj.b)

출력은 35 22입니다.

다음 코드에서는 구조체에 명시적 필드를 사용하는 방법을 보여 줍니다. 구조체는 값 형식이므로 해당 필드 값이 0으로 설정되는 기본 생성자를 자동으로 갖습니다. 따라서 DefaultValue 특성이 필요하지 않습니다.

type MyStruct =
    struct 
        val mutable myInt : int
        val mutable myString : string
    end 

let mutable myStructObj = new MyStruct()
myStructObj.myInt <- 11
myStructObj.myString <- "xyz"

printfn "%d %s" (myStructObj.myInt) (myStructObj.myString)

출력은 11 xyz입니다.

명시적 필드는 루틴에 사용하기 위한 것이 아닙니다. 일반적으로는 가능한 경우 항상 명시적 필드 대신 클래스의 let 바인딩을 사용해야 합니다. 명시적 필드는 네이티브 API에 대한 플랫폼 호출에 사용할 구조체를 정의해야 하는 경우 등과 같은 특정 상호 운용성 시나리오나 COM interop 시나리오에서 유용하게 사용됩니다. 자세한 내용은 외부 함수(F#)를 참조하십시오. 명시적 필드가 필요할 수 있는 또 다른 상황으로는 기본 생성자가 없는 클래스를 만드는 F# 코드 생성기를 사용하여 작업해야 하는 경우를 들 수 있습니다. 명시적 필드는 스레드에 정적인 변수나 그와 유사한 구문에도 유용하게 사용됩니다. 자세한 내용은 ThreadStaticAttribute를 참조하십시오.

때 키워드 member val 표시 함께 형식 정의를 자동으로 구현 된 속성의 정의 것입니다. 자세한 내용은 속성(F#)를 참조하십시오.

참고 항목

참조

속성(F#)

클래스의 let 바인딩(F#)

기타 리소스

멤버(F#)