結構是精簡的物件類型,比具有少量數據和簡單行為的型別的類別更有效率。
語法
[ attributes ]
type [accessibility-modifier] type-name =
struct
type-definition-elements-and-members
end
// or
[ attributes ]
[<StructAttribute>]
type [accessibility-modifier] type-name =
type-definition-elements-and-members
備註
結構是 實值型別,這表示它們會直接儲存在堆棧上,或當它們當做字段或陣列元素使用時,內嵌在父類型中。 不同於類別和記錄,結構具有逐值傳遞語意。 這表示它們主要適用於經常存取和複製的數據小型匯總。
在上一個語法中,會顯示兩種窗體。 第一個不是輕量型語法,但它仍然經常使用,因為當您使用 struct 和 end 關鍵詞時,可以省略 StructAttribute 屬性,該屬性會出現在第二個窗體中。 您可以StructAttribute縮寫為 。Struct
上一個語法中的 type-definition-elements-and-members 代表成員宣告和定義。 結構可以有建構函式和可變和不可變的欄位,而且可以宣告成員和介面實作。 如需詳細資訊,請參閱 成員。
結構無法參與繼承、不能包含 let 或 do 系結,而且不能以遞歸方式包含本身類型的欄位(雖然可以包含參考單元格參考自己的類型)。
因為結構不允許 let 系結,因此您必須使用 val 關鍵詞宣告結構中的欄位。
val關鍵詞會定義欄位及其類型,但不允許初始化。 相反地, val 宣告會初始化為零或 Null。 基於這個理由,具有隱含建構函式的結構(也就是宣告中結構名稱之後所提供的參數)需要 val 以 DefaultValue 屬性標註宣告。 具有已定義建構函式的結構仍支援零初始化。 因此,屬性是一個宣告, DefaultValue 表示這類零值對欄位有效。 結構的隱含建構函式不會執行任何動作,因為 let 和 do 系結不允許在型別上執行,但傳入的隱含建構函式參數值可作為私用字段使用。
明確建構函式可能涉及域值的初始化。 當您有具有明確建構函式的結構時,仍支援零初始化;不過,您不會在 DefaultValue 宣告上使用 val 屬性,因為它與明確建構函式衝突。 如需宣告的詳細資訊 val ,請參閱 明確欄位: val 關鍵詞。
結構允許屬性和輔助功能修飾詞,並遵循與其他類型相同的規則。 如需詳細資訊,請參閱 屬性 和 訪問控制。
下列程式代碼範例說明結構定義。
// In Point3D, three immutable values are defined.
// x, y, and z will be initialized to 0.0.
type Point3D =
struct
val x: float
val y: float
val z: float
end
// In Point2D, two immutable values are defined.
// It also has a member which computes a distance between itself and another Point2D.
// Point2D has an explicit constructor.
// You can create zero-initialized instances of Point2D, or you can
// pass in arguments to initialize the values.
type Point2D =
struct
val X: float
val Y: float
new(x: float, y: float) = { X = x; Y = y }
member this.GetDistanceFrom(p: Point2D) =
let dX = (p.X - this.X) ** 2.0
let dY = (p.Y - this.Y) ** 2.0
dX + dY |> sqrt
end
ByRefLike 結構
您可以定義可遵守 byref類似語意的您自己的結構:如需詳細資訊,請參閱 Byrefs 。 這是使用 IsByRefLikeAttribute 屬性完成的:
open System
open System.Runtime.CompilerServices
[<IsByRefLike; Struct>]
type S(count1: Span<int>, count2: Span<int>) =
member x.Count1 = count1
member x.Count2 = count2
IsByRefLike 不代表 Struct。 這兩者都必須存在於類型上。
F# 中的 「byref-like」 結構是堆疊系結實值類型。 它絕不會在Managed堆積上配置。
byref類似 結構適用於高效能程式設計,因為它會強制執行一組關於存留期和非擷取的強式檢查。 規則如下:
- 它們可作為函式參數、方法參數、局部變數、方法傳回。
- 它們不可以是類別或一般結構的靜態或實例成員。
- 任何關閉建構 (
async方法或 Lambda 運算式) 都無法擷取它們。 - 它們不能當做泛型參數使用。
雖然這些規則非常有力地限制使用方式,但它們會以安全的方式履行高效能運算的承諾。
ReadOnly 結構
您可以使用 屬性標註結構 IsReadOnlyAttribute 。 例如:
[<IsReadOnly; Struct>]
type S(count1: int, count2: int) =
member x.Count1 = count1
member x.Count2 = count2
IsReadOnly 不代表 Struct。 您必須同時新增這兩者 IsReadOnly ,才能有 結構。
使用這個屬性會發出元資料,讓 F# 和 C# 分別將其視為 inref<'T> 和 in ref。
在唯讀結構內定義可變值會產生錯誤。
結構記錄和歧視聯集
您可以使用 屬性,將 記錄 和 歧視聯集 表示為結構 [<Struct>] 。 請參閱每個文章以深入瞭解。