Подтвердить что ты не робот

Невозможно разрешить метод F #, который был переопределен и перегружен с С#

Следующий код F # объявляет базовые и потоковые классы. Базовый класс имеет виртуальный метод "Тест" с реализацией по умолчанию. Класс потомков переопределяет метод базового класса, а также добавляет новый перегруженный метод "Тест" . Этот код отлично компилируется и не представляет проблем при доступе к методу "Test", принадлежащему потомству.

F # Код:

module OverrideTest
  [<AbstractClass>]
  type Base() =
    abstract member Test : int -> int
    default this.Test x = x + 1

  type Descendant() =
    inherit Base()
    override this.Test x    = x - 1
    member this.Test (x, y) = x - y

Однако попытка вызвать переопределение потомка 'Test' из С# приводит к ошибке компиляции:

var result = td.Test(3); < - Нет перегрузки для метода "Тест" принимает 1 аргумент

Полный код С#:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Client
{
  class Program
  {
    static void Main(string[] args)
    {
      var td = new OverrideTest.Descendant();
      var result = td.Test(3);
      Console.WriteLine(result);
      Console.ReadKey();
    }
  }
}

Странно то, что VisualStudio intellisense видит две перегруженные функции и предоставляет правильные подписи для обоих. Он не дает никаких предупреждений или ошибок, прежде чем сборка завершится неудачей, и только подсветит линию позже.

Я полностью выполнил этот сценарий полностью на С# и не столкнулся с той же проблемой.

У кого-нибудь есть идеи, что здесь происходит?

4b9b3361

Ответ 1

Без сомнения, вы знаете, что если вы опустите член Test(x,y) из типа Descendant или просто переименуете его Test2(x,y) - тогда код С# будет компилироваться и выполняться как ожидалось.

Взгляд на IL, сгенерированный для вашего исходного типа Descendant, предлагает ключ:

.method public hidebysig virtual
    instance int32 Test (
        int32 x
    ) cil managed ...

.method public 
    instance int32 Test (
        int32 x,
        int32 y
    ) cil managed ...

Обратите внимание, что атрибут hidebysig отсутствует в методе Test(x,y).

спецификация CLI ECMA имеет следующие значения hidebysig. (Раздел 15.4.2.2, выделение жирным шрифтом - мое.)

hidebysig предоставляется для использования инструментов и игнорируется VES. Он указывает, что объявленный метод скрывает все методы типы базового класса, которые имеют подпись метода соответствия; , когда опущен, метод должен скрывать все методы с тем же именем, независимо от подписи.

Итак, компилятор F # опускает атрибут hidebysig, что означает, что метод Test(x,y) скрывает все другие методы с именем Test. Хотя hidebysig является только "для использования инструментов", похоже, что компилятор С# является одним из тех инструментов, которые его используют!

Мне кажется, что это может быть ошибкой в ​​компиляторе F #, но поскольку я никогда не рассматривал спецификацию F #, всегда возможно, что это допустимое/заданное поведение.