无法从 class 转换为通用接口
Cannot convert from class to generic interface
编辑:已更新以包含实际代码。
我在使用一些自定义通用接口时遇到问题,我不确定该怎么做。我得到的错误是:
Cannot convert from Map
to IMap<ICell>
当我尝试将 Map
作为参数传递给接受 IMap<ICell>
的方法时,会出现该错误。我在下面粘贴了示例代码。需要明确的是,FieldOfView
不使用任何未在 ICell
或 IMap
.
中定义的内容
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 相似,但略有不同。我尝试实现接口 IMap
和 IMap<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>();
因为 list
是 IEnumerable<
out
T>
,这意味着每个 IEnumerable<TT>
与 [=从 T
派生的 19=] 是 list
的有效值。所以 List
不一定是 object
,它可以是任何派生类型。
但是因为你不能使用方差,我们需要另一个 hack。
可能的解决方案:不是从 IMap<Cell>
导出 Map
,而是从 IMap<ICell>
导出它。您只需更正一些点,例如 GetCell()
的 return 类型必须变为 ICell
而不是 Cell
。适合你吗?
编辑:已更新以包含实际代码。
我在使用一些自定义通用接口时遇到问题,我不确定该怎么做。我得到的错误是:
Cannot convert from
Map
toIMap<ICell>
当我尝试将 Map
作为参数传递给接受 IMap<ICell>
的方法时,会出现该错误。我在下面粘贴了示例代码。需要明确的是,FieldOfView
不使用任何未在 ICell
或 IMap
.
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 相似,但略有不同。我尝试实现接口 IMap
和 IMap<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
andIMap<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>();
因为 list
是 IEnumerable<
out
T>
,这意味着每个 IEnumerable<TT>
与 [=从 T
派生的 19=] 是 list
的有效值。所以 List
不一定是 object
,它可以是任何派生类型。
但是因为你不能使用方差,我们需要另一个 hack。
可能的解决方案:不是从 IMap<Cell>
导出 Map
,而是从 IMap<ICell>
导出它。您只需更正一些点,例如 GetCell()
的 return 类型必须变为 ICell
而不是 Cell
。适合你吗?