2013-03-01 5 views

risposta

3

Le funzioni inline non sono integrate direttamente nel codice di chiamata? In tal caso, non viene chiamato alcun metodo effettivo in quanto il codice è "in linea" e per ogni posizione in cui sono utilizzati viene fornita una nuova copia del codice inserito.

+0

Probabilmente è corretto. Speravo di ottenere una risposta del tipo: c'è un interruttore del compilatore F # che può disattivare globalmente tutte le funzioni inline. Ma immagino che non esista niente del genere ... –

+0

Le impostazioni per f # sono [qui] (http://msdn.microsoft.com/en-us/library/dd233171.aspx) non possono vedere nulla di appropriato. Quando dici che non è coperto come in realtà viene mostrato come scoperto perché il PDB probabilmente non avrà punti di sequenza per quelle linee e quindi non dovrebbe contrassegnarli - quindi potrebbe essere un problema di rendering. Hai provato uno strumento alternativo come [OpenCover] (https://github.com/sawilde/opencover) e vedere se produce gli stessi risultati. –

+0

Quindi, dopo un po 'di combattimenti, ho ottenuto risultati da OpenCover e i risultati sono gli stessi. Le funzioni inline non sono coperte. EDIT: puoi vedere i risultati della copertina aperta qui: https://dl.dropbox.com/u/4571/opencover/index.htm –

4

Quando si scrive una funzione inline, il compilatore inline il corpo della funzione nel codice chiamante. Come discusso nei commenti, non emette inoltre informazioni di debug per questo corpo inline (e quindi non è possibile entrare nella funzione - penso che questo possa essere risolto - inviare una richiesta a fsbugs a microsoft punto com).

Tuttavia, il compilatore genera anche una versione dinamica del codice - se si scrive dicono:

let inline add a b = a + b 

poi c'è in realtà un metodo add nel codice compilato. Il metodo sarà generico ('a -> 'b -> 'c) e utilizza la ricerca dinamica per trovare un'implementazione appropriata dell'operatore + (poiché i generici .NET non possono rappresentare tali vincoli).

L'implementazione dinamica verrà richiamato quando si utilizza la riflessione o di preventivi:

open Microsoft.FSharp.Linq.RuntimeHelpers 
<@ add 1 2 @> |> LeafExpressionConverter.EvaluateQuotation |> printfn "Got: %A" 

Se mettete punto di interruzione all'interno add ed eseguire il codice di cui sopra che il punto di interruzione saranno colpiti (e presumo lo strumento di copertura di codice segnala la funzione come coperta).

Ma tenere a mente che questo è non il codice che viene eseguito in realtà quando si scrive add 1 2 in codice normale - il codice in esecuzione qui è una diversa implementazione (che utilizza la ricerca dinamica lenta, piuttosto che inlining).

+0

Ho appena provato questo su una funzione inline con uno strumento di copertura del codice ben noto e non ha funzionato. Il test con <@ @> funzionava correttamente, ma nessun codice evidenziato. Bella idea, dovrò tenere a mente. –

+0

L'approccio di Tomas di aggiungere un test per il metodo inline tramite quotazione può essere fatto facilmente utilizzando Swensen.Unquote. La copertura si presenta sotto OpenCover e NCrunch. – marklam