F# 在F中添加额外的方法作为类型扩展#
我有一个.Net库,它已经实现了F# 在F中添加额外的方法作为类型扩展#,f#,extension-methods,F#,Extension Methods,我有一个.Net库,它已经实现了.Item方法,例如 namespace Library2 type A() = member m.Item with get(a: string) = printfn "get a string" member m.Item with get(a: int) = printfn "simple slice" 在使用此库的代码中,我想添加一个同名的额外方法(因此它是可选扩展名): 以下示例的最后一行未编译: let a = new A(
.Item
方法,例如
namespace Library2
type A() =
member m.Item with get(a: string) = printfn "get a string"
member m.Item with get(a: int) = printfn "simple slice"
在使用此库的代码中,我想添加一个同名的额外方法(因此它是可选扩展名
):
以下示例的最后一行未编译:
let a = new A()
a.["good"]
a.[10]
a.[true]
报告说:
扩展方法不能是虚拟方法或抽象方法。他们可以
重载同名的其他方法,但编译器会给出
在调用不明确的情况下,首选非扩展方法
这意味着我不能用相同的类型签名扩展
.ToString/.GetHashCode
,但这里我使用不同的类型签名。为什么新方法不能被扩展?我认为,问题是因为扩展方法的实现如下(C#):
公共静态类MyModule
{
公共静态无效项(此A、b)
{
//随便
}
}
编译器正在查找.Item(…)
方法,在原始库2.A
类中找到它,但无法搜索任何扩展方法
请注意,如果所有.Item(…)
重载都是扩展方法,则一切正常:
module Library2 =
type A() =
member m.dummy = ()
open Library2
type A with
member m.Item with get(a: string) = printfn "get a string"
member m.Item with get(a: int) = printfn "simple slice"
member m.Item with get(a: bool) = printfn "get a bool"
这似乎是编译器中的一个bug。扩展方法就在那里,当您放弃索引器附带的漂亮语法糖时,可以调用扩展方法,即: 图书馆:
namespace TestLibrary
type A() =
member m.Item with get(a: string) = "string"
member m.Item with get(a: int) = "int"
主要内容:
打开测试库
A型
成员m.具有get(a:bool)=“bool”的项
[]
让主argv=
设a=newa()
printfn“%s”(a.get\u项目“a”)
printfn“%s”(a.get\u项目1)
printfn“%s”(a.get\u项为真)
System.Console.ReadLine()|>忽略
0
我的第一个直觉是,索引器不能将
单元
作为返回类型,但这并不是问题所在。奇怪的是,我在LinqPad中创建了一个类似的东西,它按照您的预期工作
module ModuleA =
type A() =
member m.Item with get(a: string) = printfn "get a string"
member m.Item with get(a: int) = printfn "simple slice"
module ModuleB =
open ModuleA
type A with
member m.Item with get(a: bool) = printfn "get a bool"
open ModuleB
let a = new ModuleA.A()
a.["good"]
a.[10]
a.[true]
// get a string
// simple slice
// get a bool
内在扩展和可选扩展之间有区别。我的案例是
可选的
。是的,内部扩展被编译到类型本身,就像C#中的部分
类一样,这可能就是问题的原因。值得注意的是:F#支持扩展属性,但C#不支持。因此,没有一个C#对应物能与他所做的相媲美。我觉得奇怪的是,Intellisense显示了所有三个重载。是的。这让我很困惑。。。
open TestLibrary
type A with
member m.Item with get(a: bool) = "bool"
[<EntryPoint>]
let main argv =
let a = new A()
printfn "%s" (a.get_Item "a")
printfn "%s" (a.get_Item 1)
printfn "%s" (a.get_Item true)
System.Console.ReadLine() |> ignore
0
module ModuleA =
type A() =
member m.Item with get(a: string) = printfn "get a string"
member m.Item with get(a: int) = printfn "simple slice"
module ModuleB =
open ModuleA
type A with
member m.Item with get(a: bool) = printfn "get a bool"
open ModuleB
let a = new ModuleA.A()
a.["good"]
a.[10]
a.[true]
// get a string
// simple slice
// get a bool