Verwendung von F # Interactive, können Sie die folgenden Größen überprüfen:Warum hat F # generische Struktur ein zusätzliches __dummy Feld?
// 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
Der Grund für die zusätzliche Größe scheint in der generischen Fall das Vorhandensein einer ganzen Zahl __dummy
Feld zu sein. Mit F # Interactive wieder, können Sie sehen, diese typeof
mit:
typeof<A>
zeigtDeclaredFields = [|Int32 i|]
typeof<B<int>>
zeigtDeclaredFields = [|Int32 i; Int32 __dummy|]
Ich verstehe nicht, warum das __dummy
Feld hinzugefügt wurde.
Ich denke, der Code für das Hinzufügen es hier:
https://github.com/fsharp/FSharp.Compiler.Service/blob/master/src/fsharp/ilxgen.fs
Line 6377 zeigt dies:
if requiresExtraField then
yield mkILInstanceField("__dummy",cenv.g.ilg.typ_int32,None,ILMemberAccess.Assembly) ]
Line 6290 ist, wo requiresExtraField
definiert:
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
I gehe davon aus, dass isEmptyStruct
soll bedeuten, dass die Struktur keine Instanzfelder hat. Aber der geschriebene Code testet, ob die Struktur irgendwelche Instanzfelder hat, was für die meisten Strukturen, einschließlich meiner, wahr ist. Ich denke, der letzte Teil des letzten Tests ist, ob es generische Typparameter gibt. So ist requiresExtraField
false
für type A
(nicht generisch) und true
für type B
(generischer Typ).
Ist das ein Compilerfehler, oder ist der Code korrekt? Wenn es richtig ist, was ist der Zweck dieses Feldes __dummy
? Kann ich es irgendwie vermeiden?
Als weiteren Test, entfernte ich meinen ersten und einzige Instanz Feld, und nicht überraschend, ich habe folgende Größen, die zeigt, dass das __dummy
Feld wurde nicht mehr hinzugefügt:
// sizeof<AA> = 1
type AA = struct end
// sizeof<BB<int>> = 1
type BB<'T> = struct end
Der Grund mag ich habe Ein Werttyp anstelle eines Referenztyps besteht darin, dass ich viele dieser Objekte in meinen Datenstrukturen speichern und nicht nur weitergeben werde.
"cenv.opts.workAroundReflectionEmitBugs" schlägt vor, dass dies eine Problemumgehung für einige Reflektionsfehler ist. Haben Sie überprüft, ob C# dasselbe tut? - Ein kurzer Blick auf den Code-Verlauf zeigt, dass dies mindestens November 2010, F # 2, zurückreicht.0 - die früheste Version des online verfügbaren Codes AFAIK. – Asik
Seit sizeof > = 4 in einem Programm, ist seine Größe in der interaktiven wirklich ein Problem für Sie? – jyoung
@jyoung: Oh, ich habe nie realisiert, dass dies nur bei F # Interactive der Fall war. Ich habe gerade sizeof > in einem Programm, wie Sie gesagt, und es gibt 4, während F # Interactive gibt 8. Dann ist mein Problem gelöst, danke! Ich habe diese Quelldatei mit Google gefunden, daher wusste ich nicht genau, wofür sie gedacht ist. In der entsprechenden fsi-Datei besagt der öffentliche Typ "IlxAssemblyGenerator" am Ende, dass es ein inkrementeller ILX-Codegenerator für eine einzelne Assembly ist. Nur für meine Erbauung, worum geht es? – bananasareyellow