2014-11-28 16 views
10

Il compilatore F # restituisce un errore che dice che devo aggiungere un riferimento al progetto perché il tipo che sto usando ha un argomento di metodo che vive in quel progetto. Ma questo metodo è privato!Il compilatore F # richiede il riferimento del progetto, ma il metodo è privato

Ho la seguente struttura del progetto:

Programma -> Libreria -> SubLibrary

SubLibrary contiene questo:

namespace SubLibrary 

type Widget = { Value: int } 

Biblioteca contiene questo:

namespace Library 

open SubLibrary 

type Banana = 
    { Value: int } 

    member private x.TakeWidget (w: Widget) =() 

programma contiene questo:

open Library 

[<EntryPoint>] 
let main argv = 
    printfn "%A" argv 

    let banana = { Value = 42 } 
    0 

ottengo questo errore:

error FS0074: 
The type referenced through 'SubLibrary.Widget' is defined in an assembly that is not referenced. 
You must add a reference to assembly 'SubLibrary' 

Ma il metodo è TakeWidgetprivato!

Ho provato a cambiare Banana in una classe, piuttosto che in un record, ma ciò non ha fatto alcuna differenza.

Come esperimento, ho creato una versione C# di Biblioteca, chiamato CLibrary:

using SubLibrary; 

namespace CLibrary { 
    public class CBanana { 
     int m_value; 

     public CBanana(int value) { 
      m_value = value; 
     } 

     private void TakeWidget(Widget w) { 
     } 
    } 
} 

poi ho cambiato programma utilizzare CBanana invece di Banana:

open Library 

[<EntryPoint>] 
let main argv = 
    printfn "%A" argv 

    let banana = CBanana 42 
    0 

Ora non ho un errore. In effetti, con C# posso rendere pubblico quel metodo, e fintanto che non provo a compilare una chiamata, non c'è errore.

Perché il compilatore insiste per aggiungere un riferimento a SubLibrary? Certo, potrei andare avanti e fare quello che mi dice di fare, per una vita tranquilla, ma SubLibrary è un dettaglio di implementazione privato di Library, che non deve essere esposto a Programma.

risposta

2

In realtà, quando ho provato con una classe, invece di record, ha fatto il trucco (F # 3.1):

type BananaClass (value:int) = 
    member private x.TakeWidget (w: Widget) =() 
    member x.Value = value 

È possibile lavorare intorno ad esso con un record, come pure - è necessario spostare il membro privato in un modulo separato e hanno come un tipo di aumento:

type Banana = { Value: int } 

module Ext = 
    type Banana with 
     member x.TakeWidget (w: Widget) =() 

compilatore non lamentare la dipendenza mancante fino ad aprire il modulo Ext.

Non ho una buona idea del motivo per cui il compilatore si è lamentato in primo luogo. Probabilmente uno dei suoi capricci. Non sono riuscito a trovare nulla di gravemente sospetto nell'IL generato (a parte il fatto sorprendente che il compilatore F # segna sia i membri privati ​​che quelli interni come interni nell'IL - questo risultato non ha avuto alcuna conseguenza qui).

+0

Sto anche utilizzando F # 3.1 (VS 2013). Se 'Banana' è una classe, puoi compilare una chiamata al costruttore, ma se provi ad accedere alla proprietà pubblica' Value', è quando avrai l'errore. Nel mio caso, ho bisogno che il metodo sia intrinseco, perché deve essere scoperto usando il reflection, quindi un'estensione opzionale non mi è utile. Grazie per la tua risposta. – bananasareyellow

+0

In modo piuttosto sorprendente, la specifica afferma che "La forma compilata dalla CLI di tutte le entità non pubbliche è" interna "." – kaefer

Problemi correlati