Можно ли определить общий метод расширения в F #? - PullRequest
5 голосов
/ 01 августа 2010

Я пытался использовать Rhino Mocks с кодом F #, и следующий код был проблематичным:

let service = MockRepository.GenerateMock<IMyService>()
service.Stub(s => s.Name).Return("Service");

Это не было неожиданностью, поскольку Stub не является частью интерфейса IMyService, это метод расширения C #, который определяет Rhino Mocks.

Слегка измененный код работает:

let service = MockRepository.GenerateMock<IMyService>()
RhinoMocksExtensions.Stub<IMyService, string>(service, fun s -> s.Name).Return("Service");

Однако было бы неплохо определить метод расширения в F #, но тогда это будет параметризованный универсальный метод расширения, который будет принимать кортеж. Я пробовал синтаксис varios, но безуспешно. Я не нашел информации, поддерживается ли это в настоящее время в F # или нет. Если кто-нибудь знает, пожалуйста, дайте мне знать.

Ответы [ 2 ]

4 голосов
/ 01 августа 2010

Как упоминалось в kvb, это невозможно в F # 2.0. В этом конкретном случае я бы обернул свободный интерфейс Rhino.Mocks, чтобы сделать его более идиоматичным в F #, например ::

let mstub f target =
    RhinoMocksExtensions.Stub(target, Function(f))

let mreturn value (options: IMethodOptions<'a>) =
    options.Return value

let service = MockRepository.GenerateMock<IComparer>()
service |> mstub (fun s -> s.Compare(1,2)) |> mreturn 1 |> ignore

То, что свободно говорит на одном языке, не обязательно говорит на другом. (извините за пробку, но я действительно думаю, что это актуально здесь)

3 голосов
/ 01 августа 2010

Если я правильно понимаю ваш вопрос, ответ - нет. Раздел 8.12.1 спецификации (импортированные члены C # Extensions) включает этот текст:

C # -определены дополнительные элементы доступны для кода F # в средах где C # -авторная сборка ссылка и открытая декларация соответствующее пространство имен находится в эффект. Тем не менее, некоторые ограничения применять, в частности

  • C # добавочные члены, чье «это» параметр типа переменной не сделал доступным для кода F # в этом версия F #

  • C # добавочные члены, чье «это» параметр типа массива не сделал доступным для кода F # в этом версия F #

Это объясняет, почему некоторые методы расширения из C # будут работать (например, в System.Linq), а тот, который вы пытаетесь использовать, не будет.

Кроме того, собственные методы расширения F # могут быть определены только так, как если бы они были размещены в реальных определениях типов. В частности, вы не можете определить метод расширения F # для закрытого универсального типа (например, IEnumerable<string>), а также не можете определить метод расширения для переменной универсального типа.

...