使用 F# Interactive,您可以验证以下大小:
// 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
额外大小的原因似乎是存在整数 __dummy
一般情况下的字段。再次使用 F# Interactive,您可以使用 typeof
看到这一点:
-
typeof<A>
显示DeclaredFields = [|Int32 i|]
-
typeof<B<int>>
显示DeclaredFields = [|Int32 i; Int32 __dummy|]
我不明白为什么会这样 __dummy
已添加字段。
我认为负责添加它的代码在这里:
https://github.com/fsharp/FSharp.Compiler.Service/blob/master/src/fsharp/ilxgen.fs
Line 6377显示此:
if requiresExtraField then
yield mkILInstanceField("__dummy",cenv.g.ilg.typ_int32,None,ILMemberAccess.Assembly) ]
Line 6290是哪里requiresExtraField
定义为:
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
我假设isEmptyStruct
应该意味着该结构没有任何实例字段。但是编写的代码正在测试结构是否有任何实例字段,对于大多数结构(包括我的结构)来说,这都是正确的。我认为最终测试的最后一部分是是否有泛型类型参数。所以requiresExtraField
是 false
对于 type A
(非通用)和 true
对于 type B
(通用类型)。
这是编译器错误还是代码正确?如果正确的话,那么这个__dummy
的目的是什么? field ?有什么办法可以避免它吗?
作为另一项测试,我删除了唯一的实例字段,毫不奇怪,我得到了以下大小,显示 __dummy
不再添加字段:
// sizeof<AA> = 1
type AA = struct end
// sizeof<BB<int>> = 1
type BB<'T> = struct end
我想要使用值类型而不是引用类型的原因是,我将在数据结构中存储大量这些对象,而不仅仅是传递它们。
最佳答案
@jyoung 在我的原始帖子下面的评论中给出了解释。
requiresExtraField
的最后一行还测试 cenv.opts.workAroundReflectionEmitBugs
。该标志似乎是在 fscopts.fs 中设置的。代码行是:
workAroundReflectionEmitBugs=tcConfig.isInteractive; // REVIEW: is this still required?
所以额外的问题__dummy
字段仅出现在 F# Interactive 中。
关于generics - 为什么 F# 泛型结构有额外的 __dummy 字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25848604/