2014-09-15 5 views
18

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> zeigt DeclaredFields = [|Int32 i|]
  • typeof<B<int>> zeigt DeclaredFields = [|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 requiresExtraFieldfalse 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.

+0

"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

+1

Seit sizeof > = 4 in einem Programm, ist seine Größe in der interaktiven wirklich ein Problem für Sie? – jyoung

+0

@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

Antwort

1

Die Erklärung wird von @jyoung in den Kommentaren unten mein ursprüngliches Posting gegeben.

Die letzte Zeile von requiresExtraField testet auch cenv.opts.workAroundReflectionEmitBugs. Dieses Flag scheint in fscopts.fs festgelegt zu sein. Die Codezeile ist:

workAroundReflectionEmitBugs=tcConfig.isInteractive; // REVIEW: is this still required? 

So das Problem des zusätzlichen __dummy Feldes tritt nur in F # Interactive.

+0

Dies beantwortet nicht die Frage, ob die Logik für 'isEmptyStruct' rückwärts ist, wie es scheint. – ildjarn

+0

@ildjarn: Sie haben Recht, es tut es nicht. Ich markierte es als beantwortet, weil mein Hauptproblem die Größe der Struktur aufgrund des Vorhandenseins des Dummy-Felds war. Dieser Test ist immer noch fraglich. – bananasareyellow