Sử dụng F # Interactive, bạn có thể xác minh các kích thước sau:Tại sao cấu trúc chung F # có trường __dummy thừa?
// sizeof<A> = 4 bytes
type A (i: int) = struct end
// sizeof<B<int>> = 8 bytes (use any type parameter)
type B<'T> (i: int) = struct end
Lý do kích thước thêm vẻ là sự hiện diện của một __dummy
trường số nguyên trong trường hợp tổng quát. Sử dụng F # Interactive một lần nữa, bạn có thể thấy điều này bằng typeof
:
typeof<A>
lãmDeclaredFields = [|Int32 i|]
typeof<B<int>>
lãmDeclaredFields = [|Int32 i; Int32 __dummy|]
Tôi không hiểu tại sao lĩnh vực __dummy
này đã được thêm vào.
Tôi nghĩ rằng mã chịu trách nhiệm cho việc thêm nó là ở đây:
https://github.com/fsharp/FSharp.Compiler.Service/blob/master/src/fsharp/ilxgen.fs
Line 6377 thấy điều này:
if requiresExtraField then
yield mkILInstanceField("__dummy",cenv.g.ilg.typ_int32,None,ILMemberAccess.Assembly) ]
Line 6290 là nơi requiresExtraField
được định nghĩa:
let requiresExtraField =
let isEmptyStruct =
(match ilTypeDefKind with ILTypeDefKind.ValueType -> true | _ -> false) &&
// All structs are sequential by default
// Structs with no instance fields get size 1, pack 0
tycon.AllFieldsAsList |> List.exists (fun f -> not f.IsStatic)
isEmptyStruct && cenv.opts.workAroundReflectionEmitBugs && not tycon.TyparsNoRange.IsEmpty
tôi giả sử rằng isEmptyStruct
được cho là có nghĩa là cấu trúc không có bất kỳ trường mẫu nào. Nhưng mã như được viết là kiểm tra xem cấu trúc có có bất kỳ trường mẫu nào không, cho hầu hết các cấu trúc, kể cả của tôi, sẽ là đúng. Tôi nghĩ phần cuối cùng của bài kiểm tra cuối cùng là liệu có bất kỳ tham số kiểu chung nào không. Vì vậy, requiresExtraField
là false
cho type A
(không phải chung chung) và true
cho type B
(loại chung).
Đây có phải là lỗi trình biên dịch hay mã đúng không? Nếu đúng, thì mục đích của trường __dummy
này là gì? Có cách nào tôi có thể tránh được không?
Như thử nghiệm khác, tôi lấy ra một của tôi và instance field chỉ, và không đáng ngạc nhiên, tôi có các kích thước sau, cho thấy rằng lĩnh vực __dummy
đã không còn nói thêm:
// sizeof<AA> = 1
type AA = struct end
// sizeof<BB<int>> = 1
type BB<'T> = struct end
Lý do tôi muốn có một loại giá trị, chứ không phải là một kiểu tham chiếu, là tôi sẽ lưu trữ rất nhiều các đối tượng này trong các cấu trúc dữ liệu của tôi, không chỉ truyền chúng xung quanh.
"cenv.opts.workAroundReflectionEmitBugs" gợi ý rằng đây là giải pháp cho một số lỗi phát ra phản chiếu. Bạn đã kiểm tra xem C# có thực hiện điều tương tự không? - Xem nhanh lịch sử mã cho thấy ngày này trở lại ít nhất là tháng 11 năm 2010, F # 2.0 - phiên bản sớm nhất của mã có sẵn trực tuyến AFAIK. – Asik
Kể từ khi sizeof > = 4 trong một chương trình, là kích thước của nó trong tương tác thực sự là một vấn đề cho bạn? – jyoung
@ jyoung: Ồ, tôi chưa bao giờ nhận ra rằng đây chỉ là trường hợp với F # Interactive. Tôi chỉ thử sizeof > trong một chương trình, như bạn đã nói, và nó cho 4, trong khi F # Interactive cho 8. Sau đó, vấn đề của tôi được giải quyết, cảm ơn bạn! Tôi thấy rằng tập tin nguồn bằng cách sử dụng Google, vì vậy tôi không biết hình ảnh lớn hơn của nó là gì. Trong tệp fsi tương ứng, loại công khai 'IlxAssemblyGenerator' ở cuối cho biết rằng nó là _An máy phát mã ILX gia tăng cho một assembly_ duy nhất. Chỉ để chỉnh sửa của tôi, đó là tất cả những gì về? – bananasareyellow