2014-11-28 15 views
10

Der F # -Compiler gibt einen Fehler, der besagt, dass ich einen Projektverweis hinzufügen muss, da der Typ, den ich verwende, ein Methodenargument hat, das in diesem Projekt lebt. Aber diese Methode ist privat!F # -Compiler erfordert Projektverweis, aber Methode ist privat

Ich habe die folgende Projektstruktur:

Programm -> Bibliothek -> Unterbibliothek

Subbibliothek enthält diese:

namespace SubLibrary 

type Widget = { Value: int } 

Bibliothek enthält diese:

namespace Library 

open SubLibrary 

type Banana = 
    { Value: int } 

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

Programm enthält diese:

open Library 

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

    let banana = { Value = 42 } 
    0 

ich diesen Fehler:

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' 

Aber die TakeWidget Methode ist privaten!

Ich versuchte Banana in eine Klasse zu ändern, anstatt eine Aufzeichnung, aber das machte keinen Unterschied.

Als Experiment habe ich eine C# Version von Bibliothek, genannt CLibrary:

using SubLibrary; 

namespace CLibrary { 
    public class CBanana { 
     int m_value; 

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

     private void TakeWidget(Widget w) { 
     } 
    } 
} 

DannProgramm I geändert CBanana zu verwenden, anstatt Banana:

open Library 

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

    let banana = CBanana 42 
    0 

Jetzt bekomme ich keinen Fehler. Tatsächlich kann ich mit C# diese Methode öffentlich machen, und solange ich nicht versuche, einen Aufruf zu kompilieren, gibt es keinen Fehler.

Warum besteht der Compiler darauf, dass ich einen Verweis auf SubLibrary hinzufüge? Sicher, ich könnte einfach weitermachen und tun, was es mir sagt, für ein ruhiges Leben, aber SubLibrary ist ein privates Implementierungsdetail von Bibliothek, die nicht Programm ausgesetzt werden sollte.

Antwort

2

Eigentlich, wenn ich mit einer Klasse statt Rekord versucht, tat es den Trick (F # 3.1):

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

Sie können auch mit einem Rekord um es arbeiten - Sie das private Element bewegen müssen in einem separaten Modul und haben es als eine Art Augmentation:

type Banana = { Value: int } 

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

Compiler nicht über die fehlende Abhängigkeit beschweren, bis Sie das Ext Modul öffnen.

Ich habe keine gute Idee, warum der Compiler in erster Linie beschwerte. Wahrscheinlich eine seiner Eigenheiten. Ich konnte im generierten IL nichts Verdächtiges finden (abgesehen von der überraschenden Tatsache, dass der F # -Compiler sowohl private als auch interne Mitglieder als intern in der IL markiert - dies erwies sich hier als nicht wichtig).

+0

Ich benutze auch F # 3.1 (VS 2013). Wenn 'Banana' eine Klasse ist, können Sie einen Aufruf an den Konstruktor kompilieren, aber wenn Sie versuchen, auf die öffentliche 'Value'-Eigenschaft zuzugreifen, erhalten Sie den Fehler. In meinem Fall muss die Methode intrinsisch sein, weil sie mithilfe von Reflektion entdeckt werden muss, daher ist eine optionale Erweiterung für mich nicht gut. Danke für deine Antwort. – bananasareyellow

+0

Etwas überraschend, die Spezifikation besagt, dass "Die CLI kompilierte Form aller nicht-öffentlichen Einheiten ist" interne "." – kaefer