F# 编译器需要项目引用,但方法是私有的

Posted

技术标签:

【中文标题】F# 编译器需要项目引用,但方法是私有的【英文标题】:F# compiler requires project reference, but method is private 【发布时间】:2015-01-27 01:55:03 【问题描述】:

F# 编译器给出一个错误,提示我必须添加一个项目引用,因为我使用的类型有一个存在于该项目中的方法参数。 但是这个方法是私有的!

我的项目结构如下:

程序 -> 库 -> 子库

子库包含:

namespace SubLibrary

type Widget =  Value: int 

包含以下内容:

namespace Library

open SubLibrary

type Banana =
     Value: int 

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

程序包含以下内容:

open Library

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

    let banana =  Value = 42 
    0

我收到此错误:

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'

但是TakeWidget 方法是私有的

我尝试将 Banana 更改为一个类,而不是一个记录,但这没有任何区别。

作为一个实验,我创建了一个 C# 版本的 Library,名为 CLibrary

using SubLibrary;

namespace CLibrary 
    public class CBanana 
        int m_value;

        public CBanana(int value) 
            m_value = value;
        

        private void TakeWidget(Widget w) 
        
    

然后我将 Program 更改为使用 CBanana 而不是 Banana

open Library

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

    let banana = CBanana 42
    0

现在我没有收到错误消息。事实上,使用 C# 我可以将该方法公开,只要我不尝试编译对它的调用,就不会出错。

为什么编译器坚持要我添加对 SubLibrary 的引用?当然,我可以继续做它让我做的事,过上平静的生活,但是 SubLibraryLibrary 的私有实现细节,不应该暴露到程序

【问题讨论】:

【参考方案1】:

实际上,当我尝试使用类而不是记录时,它成功了(F# 3.1):

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

您也可以使用记录来解决它 - 您需要将私有成员移动到单独的模块中并将其作为类型扩充:

type Banana =  Value: int 

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

在您打开 Ext 模块之前,编译器不会抱怨缺少的依赖项。

我不知道为什么编译器首先会抱怨。可能是它的怪癖之一。我在生成的 IL 中找不到任何严重可疑的东西(除了 F# 编译器在 IL 中将私有成员和内部成员都标记为内部成员的令人惊讶的事实 - 这在这里被证明是没有意义的)。

【讨论】:

我也在使用 F# 3.1 (VS 2013)。如果Banana 是一个类,您可以编译对构造函数的调用,但如果您尝试访问公共Value 属性,那么您就会收到错误消息。就我而言,我需要方法是内在的,因为它需要使用反射来发现,所以可选的扩展对我没有好处。感谢您的回复。 不出所料,规范指出“所有非公共实体的 CLI 编译形式为 internal。”【参考方案2】:

在我看来这确实是一个错误,我在这里提出了一个问题,https://github.com/Microsoft/visualfsharp/issues/86。因此,您将能够从那里跟踪反馈。

【讨论】:

以上是关于F# 编译器需要项目引用,但方法是私有的的主要内容,如果未能解决你的问题,请参考以下文章

重载的包私有方法导致编译失败 - 这是 JLS 怪异还是 javac 错误?

F# 函数在使用独立开关编译并从另一个项目引用时更改类型

Xcodebuild 编译加速,Cocoapods 二进制化实践

java-多态和动态绑定

为啥 C# 编译器在使用 LINQ 方法 Any() 时会创建私有 DisplayClass,我该如何避免它?

C# 我定义了一个静态类编译成DLL后,在另一个项目中引用这个DLL,但访问不了里面的成员