Беда с дженериками - PullRequest
       4

Беда с дженериками

0 голосов
/ 21 октября 2011

Почему следующий код не компилируется? Это ошибка компилятора или языковая особенность? Какой лучший обходной путь?

type A() as this =
    let a = this.GetTypedObject<int>()    // a
    let b = this.GetTypedObject<string>() // b

    member this.GetTypedObject<'T>() =
        Unchecked.defaultof<'T>

Unchecked.defaultof <'T> используется только для примера, вместо него может использоваться любой вызов функции или конструктора.

Компилятор говорит, что код становится менее общим в строке (a) и отказывается компилировать строку (b). Я не могу дать точные сообщения компилятора, потому что они у меня есть на русском языке:).

Превращение метода GetTypedObject () в привязку let и удаление <'T> заканчиваются другим предупреждением компилятора, которое мне тоже не нравится. Единственный найденный мной способ - переместить GetTypedObject <'T> () в базовый класс и сделать его общедоступным. Заранее спасибо ...

Ответы [ 2 ]

4 голосов
/ 21 октября 2011

Обратите внимание, что вы можете просто добавить аннотацию типа, чтобы исправить это:

type A() as this = 
    let a = this.GetTypedObject<int>()    // a 
    let b = this.GetTypedObject<string>() // b 

    member this.GetTypedObject<'T>() : 'T = 
                                   //^^^^
        Unchecked.defaultof<'T> 

Сначала читаются подписи членов, а затем все тела let и тела элементов, когда дело доходит до порядка вывода типов.Поместив возвращаемый тип в подпись объявления, он становится видимым для let.

3 голосов
/ 21 октября 2011

Поскольку вывод типа работает сверху вниз, он встречает GetTypedObject, возвращая int, прежде чем он даже достигнет определения метода и обнаружит, что он должен быть универсальным . (Как указывает Брайан, члены читаются до let привязок ... и есть более простое решение для этого.) Я получаю следующую неприятную ошибку:

Использование функции GetTypedObject не соответствует типу, выведенному в другом месте. Предполагаемый тип функции: Test.A -> Microsoft.FSharp.Core.unit -> 'a. Тип функции, требуемой на данном этапе использования, - Test.A -> Microsoft.FSharp.Core.unit -> 'a. Эта ошибка может быть связана с ограничениями, связанными с общей рекурсией в коллекции let rec или в группе. классов. Подумайте о том, чтобы дать полную сигнатуру типа для целей рекурсивных вызовов, включая аннотации типов для типов аргументов и возвращаемых значений.

Если использование появляется после определения метода, оно работает.

type A() =
    member this.GetTypedObject<'T>() =
        Unchecked.defaultof<'T>

    member this.Test() =
      let a = this.GetTypedObject<int>()    // a
      let b = this.GetTypedObject<string>() // b
      ()

Вот обходной путь:

type A() =
  let getTypedObject() = Unchecked.defaultof<_>
  let a : int = getTypedObject()    // a
  let b : string = getTypedObject() // b

  member this.GetTypedObject<'T>() : 'T = getTypedObject()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...