明確欄位:val 關鍵字 (F#)
val 關鍵字可用來在類別或結構型別上宣告欄位但不初始化欄位。 以這種方式宣告的欄位稱為「明確欄位」(Explicit Field)。
[ static ] val [ mutable ] [ access-modifier ] field-name : type-name
備註
在類別或結構型別中定義欄位的一般方式是使用 let 繫結。 不過,let 繫結必須在類別建構函式中初始化,這不一定是可能、必要或所需的。 當您要未初始化的欄位時,可以使用 val 關鍵字。
明確欄位可以是靜態或非靜態。 access-modifier 可以是 public、private 或 internal。 明確欄位預設都是公用。 這不同於類別中一定是私用的 let 繫結。
在具有主要建構函式的類別型別中,明確欄位需要 DefaultValue 屬性。 這個屬性指定欄位會初始化為零。 欄位的型別必須支援零初始設定。 如果型別是下列其中一項,型別會支援零初始設定:
有零值的基本型別。
支援 null 值做為一般值、異常值或值表示的型別。 這包含類別、Tuple、記錄、函式、介面、.NET 參考型別、unit 型別和差別等位型別。
.NET 實值型別。
其所有欄位都支援預設零值的結構。
下列程式碼示範明確欄位的用法,並示範在有主要建構函式之類別中的 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。
下列程式碼示範在結構中明確欄位的用法。 因為結構為實值型別,所以它會自動具有將欄位值設為零的預設建構函式。 因此不需要 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。