2014-11-28 12 views
10

Kompilator F # podaje komunikat o błędzie, że muszę dodać odniesienie do projektu, ponieważ typ, którego używam, ma argument metody, który występuje w tym projekcie. Ale ta metoda jest prywatna!Kompilator F # wymaga odniesienia do projektu, ale metoda jest prywatna.

Mam następujące struktury projektu:

program -> Biblioteka -> subbiblioteki

subbiblioteki zawiera to:

namespace SubLibrary 

type Widget = { Value: int } 

Biblioteka zawiera to:

namespace Library 

open SubLibrary 

type Banana = 
    { Value: int } 

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

Program zawiera to:

open Library 

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

    let banana = { Value = 42 } 
    0 

otrzymuję ten błąd:

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' 

Ale metoda TakeWidget jest prywatny!

Próbowałem zmienić Banana w klasę, a nie w rejestr, ale to nie miało znaczenia.

W ramach eksperymentu, stworzyłem wersję C# z Biblioteki, zwany CLibrary:

using SubLibrary; 

namespace CLibrary { 
    public class CBanana { 
     int m_value; 

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

     private void TakeWidget(Widget w) { 
     } 
    } 
} 

Potem zmienił Program używać CBanana zamiast Banana:

open Library 

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

    let banana = CBanana 42 
    0 

Teraz nie dostaję błędu. W rzeczywistości, z C# mogę uczynić tę metodę publiczną i dopóki nie próbuję skompilować wywołania, nie ma błędu.

Dlaczego kompilator nalega, aby dodać odniesienie do Podbiblioteki? Pewnie, mógłbym po prostu robić to, co mi kazano, na spokojne życie, ale SubLibrary to prywatny szczegół implementacji Biblioteka, który nie powinien być narażony na działanie Programu.

Odpowiedz

2

Faktycznie, kiedy próbowałem z klasą zamiast rekordu, to załatwiło sprawę (F # 3.1):

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

można obejść go z rejestru, jak również - trzeba przenieść element prywatnej w osobnym module i mieć go jako powiększania typu:

type Banana = { Value: int } 

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

kompilator nie będzie narzekać na brakujące zależność momentu otwarcia modułu Ext.

Nie mam pojęcia, dlaczego kompilator narzekał w pierwszej kolejności. Prawdopodobnie jedno z jego dziwactw. Nie mogłem znaleźć niczego poważnie podejrzanego w wygenerowanym IL (poza zaskakującym faktem, że kompilator F # zaznacza zarówno prywatnych, jak i wewnętrznych członków jako wewnętrznych w IL - nie okazało się to bez znaczenia).

+0

Używam również F # 3.1 (VS 2013). Jeśli 'Banana' jest klasą, możesz skompilować wywołanie do konstruktora, ale jeśli spróbujesz uzyskać dostęp do publicznej właściwości' Value', wtedy dostaniesz błąd. W moim przypadku potrzebuję, aby ta metoda była wewnętrzna, ponieważ musi zostać odkryta za pomocą refleksji, więc opcjonalne rozszerzenie nie jest dla mnie dobre. Dzięki za odpowiedź. – bananasareyellow

+0

Nieco niespodziewanie, specyfikacja stwierdza, że ​​"CLI skompilowana forma wszystkich niepublicznych podmiotów jest" wewnętrzna "." – kaefer

Powiązane problemy