无法从 class 转换为通用接口

Cannot convert from class to generic interface

编辑:已更新以包含实际代码。

我在使用一些自定义通用接口时遇到问题,我不确定该怎么做。我得到的错误是:

Cannot convert from Map to IMap<ICell>

当我尝试将 Map 作为参数传递给接受 IMap<ICell> 的方法时,会出现该错误。我在下面粘贴了示例代码。需要明确的是,FieldOfView 不使用任何未在 ICellIMap.

中定义的内容
public class Map : IMap<Cell>
{
    private FieldOfView _fieldOfView;
    public int Width { get; }
    public int Height { get; }
    public Map(int width, int height)
    {
        Width = width;
        Height = height;
        _fieldOfView = new FieldOfView(this as IMap<ICell>);
        _fieldOfView = new FieldOfView((IMap<ICell>)this);
    }
    public IEnumerable<Cell> GetAllCells()
    {
        for (int x = 0; x < Width; x++)
        {
            for (int y = 0; y < Height; y++)
            {
                yield return GetCell(x, y);
            }
        }
    }
    public Cell GetCell(int x, int y)
    {
        return new Cell(x, y);
    }
    public void Copy(IMap<Cell> sourceMap)
    {
        // ...
    }
    public override string ToString()
    {
        var sb = new StringBuilder();
        foreach (var cell in GetAllCells())
        {
            sb.Append(cell.ToString());
        }
        return sb.ToString();
    }
}

public interface IMap<T> where T : ICell
{
    int Width { get; }
    int Height { get; }
    IEnumerable<T> GetAllCells();
    T GetCell(int x, int y);
    void Copy(IMap<T> sourceMap);
}

public class Cell : ICell
{
    public int X { get; }
    public int Y { get; }
    public Cell(int x, int y)
    {
        X = x;
        Y = Y;
    }
    public override string ToString()
    {
        return "overloaded";
    }
}

public interface ICell
{
    int X { get; }
    int Y { get; }
}

public class FieldOfView
{
    private readonly IMap<ICell> _map;
    public FieldOfView(IMap<ICell> map)
    {
        _map = map;
    }
    public void DoStuff()
    {
        foreach (var cell in _map.GetAllCells())
        {
            // ...
        }
    }
}

这与 this stack overflow question 相似,但略有不同。我尝试实现接口 IMapIMap<T> : IMap where T : ICell,但我也遇到了问题。

最后,我不确定这是否可以用 co/contravariance 解决,但我使用的是 C#3.0,所以这对我来说是不可能的(除非切换版本是唯一的方法)。


我认为隐式/直接转换会好吗?

_fieldOfView = new FieldOfView(this as IMap<ICell>); // or
_fieldOfView = new FieldOfView((IMap<ICell>)this);

但如果有更好的方法,我也愿意这样做。当我将 Map 转换为 IMap<ICell> 时,Resharper 会向我发出警告说:

Suspicious cast: there is no type in the solution which is inherited from both Map and IMap<ICell>.

EDIT2:看起来两种转换都不起作用。我决定改为从 IMap 派生 Map 并在代码中需要的地方创建 Cell 对象。

感谢@Rob 和@MK87 的帮助!

没有IMap<Cell>IMap<ICell>相同,所以这一行:

_fieldOfView = new FieldOfView(this as IMap<ICell>);

将始终传递 null 作为参数。

,这绝对可以用方差.

解决

例如,您可以:

IEnumerable<object> list = new List<string>();

因为 listIEnumerable<outT>,这意味着每个 IEnumerable<TT> 与 [=从 T 派生的 19=] 是 list 的有效值。所以 List 不一定是 object,它可以是任何派生类型。

但是因为你不能使用方差,我们需要另一个 hack。

可能的解决方案:不是从 IMap<Cell> 导出 Map,而是从 IMap<ICell> 导出它。您只需更正一些点,例如 GetCell() 的 return 类型必须变为 ICell 而不是 Cell。适合你吗?