繁体   English   中英

从C#应用程序调用时,为什么f#中实现的类型与C#类型的行为不一样?

[英]Why doesn't type implemented in f# behave the same as C# types when called from C# application?

我正在将我的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

问题是,我需要从我的C#应用​​程序中调用这个F#库。 在使用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#实现中显然有些问题(显然),但是什么?

您的F#类型与C#类型的行为不同,因为它与C#类型不同。 C#one将T参数声明为“out”:

public interface IMatch<out T> where T : IGame

也就是说out装置类型参数T是协变,而这正是允许从隐式转换SoccerMatch (这是IMatch<SoccerGame>IMatch<IGame>

但是,据我所知,F#不支持通用接口中的协方差\\逆变。 多年来一直有人建议,但问题仍然存在。 所以你的F#接口类似于这个C#one:

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

哪个会产生相同的编译时错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM