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 的引用?当然,我可以继续做它让我做的事,过上平静的生活,但是 SubLibrary 是 Library 的私有实现细节,不应该暴露到程序。
【问题讨论】:
【参考方案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 错误?
Xcodebuild 编译加速,Cocoapods 二进制化实践