Почему типы, реализованные в f #, не ведут себя так же, как типы C # при вызове из приложения C #? - PullRequest
0 голосов
/ 21 мая 2018

Я в процессе переноса моего кода C # в библиотеку F #.У меня есть следующие интерфейсы / классы в моей библиотеке C #:

public interface IMatch<out T> where T : IGame
{
    IEnumerable<T> Games { get; }
}

public interface IGame
{
    string Name { get; }
}

public class SoccerMatch : IMatch<SoccerGame>
{
    public SoccerMatch(IEnumerable<SoccerGame> games)
    {
        Games = games;
    }

    public IEnumerable<SoccerGame> Games { get; }
}

public class SoccerGame : IGame
{
    public SoccerGame(string name)
    {
        Name = name;
    }

    public string Name { get; }
}

Я попытался перенести это на F #, вот что я придумал:

type IGame =
    abstract member Name: string with get

type IMatch<'T when 'T :> IGame> =
    abstract member Games: IEnumerable<'T> with get

type SoccerGame =
    {Name: string}
    interface IGame with
        member this.Name with get() = this.Name

type SoccerMatch =
    { Games: IEnumerable<SoccerGame>}
    interface IMatch<SoccerGame> with
        member this.Games: IEnumerable<SoccerGame> = this.Games

Проблема в том, что мне нужно вызвать эту библиотеку F # из моего приложения C #.Раньше, при использовании классов C #, я мог делать следующее:

var match= new SoccerMatch(new List<SoccerGame>());
IMatch<IGame> interfaceType = match;

Но когда я пытаюсь сделать то же самое с моей библиотекой F #, например:

var match = new SoccerMatch(new List<SoccerGame>());
IMatch<IGame> interfaceType = match;

, я получаюследующая ошибка: Ошибка CS0029 Невозможно неявно преобразовать тип 'FSharp.SoccerMatch' в 'FSharp.IMatch'

Я думаю, что что-то должно быть не так в моей реализации F # (очевидно), но что?

1 Ответ

0 голосов
/ 21 мая 2018

Ваш тип F # не ведет себя так же, как C # one, потому что он не совпадает с C # one.C # one имеет параметр T, объявленный как "out":

public interface IMatch<out T> where T : IGame

То, что out означает, что параметр типа T является ковариантным, и это именно то, что позволяет неявное преобразование из SoccerMatch (что является *От 1008 *) до IMatch<IGame>.

Однако, насколько я знаю, F # не поддерживает ковариацию \ контравариантность в универсальных интерфейсах.Это было предложено годами, но выпуск все еще открыт.Таким образом, ваш интерфейс F # является аналогом этого C # one:

public interface IMatch <T> where T : IGame
{
    IEnumerable<T> Games { get; }
}

, который выдаст ту же ошибку во время компиляции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...