2014-09-15 9 views
18

Utilizzando F # Interactive, è possibile verificare le seguenti dimensioni:Perché la struttura generica F # ha un campo extra __dummy?

// 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 

La ragione per la dimensione in più sembra essere la presenza di un campo intero __dummy nel caso generico. Utilizzando ancora una volta F # Interactive, si può vedere questo utilizzando typeof:

  • typeof<A> mostra DeclaredFields = [|Int32 i|]
  • typeof<B<int>> mostra DeclaredFields = [|Int32 i; Int32 __dummy|]

Non capisco il motivo per cui questo campo __dummy è stato aggiunto.

penso che il codice responsabile per l'aggiunta è qui:

https://github.com/fsharp/FSharp.Compiler.Service/blob/master/src/fsharp/ilxgen.fs

Line 6377 mostra questo:

if requiresExtraField then 
    yield mkILInstanceField("__dummy",cenv.g.ilg.typ_int32,None,ILMemberAccess.Assembly) ] 

Line 6290 è dove requiresExtraField è definito:

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 supponiamo che isEmptyStruct significa che la struttura non ha campi di istanze. Ma il codice come scritto sta testando se la struct ha ha qualsiasi campo di istanza, che per la maggior parte delle strutture, incluso il mio, sarà vero. Penso che l'ultima parte del test finale sia se ci sono dei parametri di tipo generico. Così requiresExtraField è false per type A (non generici) e true per type B (tipo generico).

Si tratta di un bug del compilatore, o è il codice corretto? Se è corretto, qual è lo scopo di questo campo __dummy? C'è un modo per evitare di averlo?

Come un altro test, ho rimosso il mio unico e solo campo di istanza, e non a caso, ho ottenuto le seguenti dimensioni, mostrando che il campo __dummy non è stato aggiunto:

// sizeof<AA> = 1 
type AA = struct end 

// sizeof<BB<int>> = 1 
type BB<'T> = struct end 

Il motivo voglio avere un tipo di valore, piuttosto che un tipo di riferimento, è che conserverò molti di questi oggetti nelle mie strutture dati, non solo passandoli in giro.

+0

"cenv.opts.workAroundReflectionEmitBugs" suggerisce che questa soluzione è una soluzione per emettere un bug di riflessione. Hai controllato se C# fa la stessa cosa? - Una rapida occhiata alla cronologia del codice mostra che questo risale almeno a novembre 2010, F # 2.0 - la prima versione del codice disponibile online AFAIK. – Asik

+1

Dal momento che sizeof > = 4 in un programma, la sua dimensione nell'interattivo è davvero un problema per te? – jyoung

+0

@jyoung: Oh, non ho mai realizzato che questo fosse il caso solo con F # Interactive. Ho appena provato sizeof > in un programma, come hai detto tu, e dà 4, mentre F # Interactive dà 8. Quindi il mio problema è risolto, grazie! Ho trovato il file sorgente usando Google, quindi non conoscevo l'immagine più ampia di cosa fosse. Nel file fsi corrispondente, il tipo pubblico 'IlxAssemblyGenerator' alla fine dice che è _Un generatore di codice ILX incrementale per un singolo assembly_. Solo per la mia edificazione, di cosa si tratta? – bananasareyellow

risposta

1

La spiegazione è data dal @jyoung nei commenti qui sotto il mio post originale.

L'ultima riga di requiresExtraField verifica anche cenv.opts.workAroundReflectionEmitBugs. Questo flag sembra essere impostato su fscopts.fs. La riga di codice è:

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

Quindi il problema del __dummy campo aggiuntivo si verifica solo in F # Interactive.

+0

Questo non risponde alla domanda se la logica per 'isEmptyStruct' è indietro, come sembra essere. – ildjarn

+0

@ildjarn: hai ragione, non è così. L'ho contrassegnato come risposta perché il mio problema principale era la dimensione della struttura dovuta alla presenza del campo fittizio. Quel test è ancora discutibile. – bananasareyellow

Problemi correlati