2012-11-16 5 views
5

. .Item 메소드를 이미 구현 한 .Net 라이브러리가 있습니다. 이 라이브러리를 사용하는 코드에서 F #의 유형 확장자로 추가 메소드 추가

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" 

, 나는 동일한 이름의 하나 추가 방법을 추가 할 (그러므로 optional extensions입니다) :

#r @"Library2.dll" 
open Library2 
type A with 
    member m.Item with get(a: bool) = 
     printfn "get a bool" 

다음 예제의 마지막 줄은 컴파일되지 않습니다 :

let a = new A() 
a.["good"]  
a.[10] 
a.[true] 

F# doc는 말한다 :

확장 메서드는 가상 메서드 나 추상 메서드가 될 수 없습니다. 그들은 같은 이름의 다른 메서드를 오버로드 할 수 있지만 모호한 호출의 경우에는 컴파일러가 확장이 아닌 메서드에 환경 설정을 제공합니다.

즉, .ToString/.GetHashCode을 동일한 유형의 시그니처로 확장 할 수 없지만 다른 형식 시그니처를 사용합니다. 새로운 방법을 확장 할 수없는 이유는 무엇입니까? 원래 Library2.A 클래스를 발견,

public static class MyModule 
{ 
    public static void Item(this A a, bool b) 
    { 
     // whatever 
    } 
} 

이 컴파일러는 .Item(...) 방법을 찾고, 그리고 실패

+0

이상한 점은 Intellisense가 세 가지 과부하를 모두 표시한다는 것입니다. – Daniel

+0

예. 이것은 나를 혼란스럽게합니다 ... –

답변

0

내 생각은, 문제는 확장 메서드는 다음 (C 번호)로 구현되는 사실에 의해 발생 모든 확장 메소드를 검색합니다. 모든.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" 
+0

본질적인 확장과 선택적 확장 사이에는 차이가 있습니다. 내 경우는 '선택 사항'입니다. –

+0

예, 내장 함수 확장은 C#의'partial' 클래스와 마찬가지로 형식 자체로 컴파일됩니다. [선택적 확장 멤버는 개체 인스턴스가 암시 적으로 첫 번째 매개 변수로 전달되는 정적 멤버로 컴파일됩니다.] (http://msdn.microsoft.com/en-us/library/dd233211.aspx) 문제가 발생합니다. – bytebuster

+0

주목할 가치가 있습니다. F #은 확장 속성을 지원하지만 C#은 지원하지 않습니다.그래서 그가하려고하는 것에 대응하는 C#은 없습니다. – Daniel

0

이것은 컴파일러의 버그가 될 것으로 보인다. 확장 방법이있다 당신이 인덱서와 함께 제공되는 좋은 문법 설탕을 멀리 할 때이 작품 즉, 호출 할 수 있습니다

라이브러리 :

namespace TestLibrary 

type A() = 
    member m.Item with get(a: string) = "string" 
    member m.Item with get(a: int) = "int" 

홈페이지 :

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 

내 첫

직관은 인덱서가 반환 유형으로 unit을 가질 수 없다는 것이었지만 문제가되지 않았습니다.

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 
관련 문제