Полностью квалифицированное имя, неквалифицированное имя с объявлением импорта разрешает по-разному

Это работает

open System
let f = Action(fun () -> Unchecked.defaultof<_>)

Но это

let f = System.Action(fun () -> Unchecked.defaultof<_>)

создает ошибку компиляции

Существует несколько типов, называемых "Action", с разными номерами общих параметров. Предоставить экземпляр типа для устранения неоднозначности разрешения типа, например. 'Действие <, _,, _,, _ > '.

Я знаю, что могу исправить это, добавив заполнитель типа типа (System.Action<_>(...)), но любая идея, почему они ведут себя по-другому?

ИЗМЕНИТЬ

Обнаружено это в спецификации, раздел 14.1.9:

Когда открывается группа декларации модуля или пространства имен F, элементы добавляются в среду имен следующим образом:

  • Добавьте тип в таблицу TypeNames. Если тип имеет общее имя CLI, такое как List'1, тогда добавляется запись как под List, так и List'1.

Является ли это поведение реплицированным для полностью квалифицированных типов (с пропущенными параметрами типа)? Это не так.

Ответ 1

Я согласен с @James, что это связано с ошибкой, представленной на Connect, но я думаю, что это немного другой случай. Во всяком случае, я думаю, что это не намеренное поведение. Не могли бы вы сообщить об этом fsbugs в microsoft dot com?

В любом случае - я немного отлаживал, и вот что я нашел до сих пор:

Кажется, что компилятор использует разные пути кода для разрешения имени Action и имени System.Action. При разрешении другого он ищет все загруженные модули (т.е. сборки) для типа с именем System.Action (см. ResolveLongIndentAsModuleOrNamespaceThen в nameres.fs file версии с открытым исходным кодом).

Это находит два определения Action (один в mscorlib и другой в System.Core). Я думаю, проблема связана с тем, что разрешение имен просто выполняется по результатам - он находит первый (от System.Core), который не имеет полезной перегрузки (поскольку он варьируется от Action<_,_,_,_,_> до версии с около 15 параметров типа). После обнаружения этого типа он сообщает об ошибке, даже не глядя, есть ли другой тип (в другой сборке), который можно было бы использовать.

Если вы не ссылаетесь на системные сборки, то компилятор F # разрешает перегрузку просто отлично. Запуск компилятора без параметров ссылается на сборку по умолчанию, поэтому это не работает:

fsc test.fs 

но если я добавлю флаг --noframework, тогда он компилируется без проблем:

fsc --noframework test.fs