C#具有多种类型的通用列表
我可能对标题的措词不正确,但基本上我想做的是有一个相同对象的列表,其中包含不同的泛型类型 举个例子,我有一个塔防游戏,它使用基于瓷砖的地图。所以我有层(瓷砖层,对象层,ai层)。所以我有一节课:C#具有多种类型的通用列表,c#,generics,C#,Generics,我可能对标题的措词不正确,但基本上我想做的是有一个相同对象的列表,其中包含不同的泛型类型 举个例子,我有一个塔防游戏,它使用基于瓷砖的地图。所以我有层(瓷砖层,对象层,ai层)。所以我有一节课: public class Layer<T>{ // The name of the layer private String name; // All the cells in this layer private Cell<T>[] cel
public class Layer<T>{
// The name of the layer
private String name;
// All the cells in this layer
private Cell<T>[] cells;
public Layer(Map map, String name){
cells = new Cell<T>[map.Width * map.Height];
this.name = name;
CreateCells();
}
/// <summary>
/// Fills the array of cells with blank, unoccupied cells
/// </summary>
private void CreateCells(){
var index = 0;
for (var x = 0; x < cells.Length; x++){
for (var y = 0; y < cells.Length; y++){
cells[index] = new Cell<T>(x, y);
index++;
}
}
}
// Gets the array of cells in this layer
public Cell<T>[] GetCells(){
return cells;
}
/// <summary>
/// Gets a cell at a specific index/coordinate
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns>The cell at the X and Y coordinate/index</returns>
public Cell<T> GetCellAt(int x, int y){
foreach (var c in cells){
if (c.GetX() != x || c.GetY() != y) continue;
return c;
}
throw new Exception("Cell not found at " + x+"x"+y);
}
/// <summary>
/// Gets the name of this layer
/// </summary>
/// <returns></returns>
public String GetName(){
return name;
}
}
泛型也已从Cell类中删除:
public class Cell{
// The object inside this cell
private GameObject occupant; // Note the new occupant type
// The width and height of the cell in world coordinates
public const float WIDTH = 1, HEIGHT = 1;
// The coordinate of this cell
private int x, y;
}
现在我在Cell类中使用一个通用方法,如下所示:
/// <summary>
/// Gets the occupant in this cell
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public T GetOccupant<T>() where T : GameObject{
return occupant as T;
}
//
///获取此单元格中的占用者
///
///
///
public T getOccount(),其中T:GameObject{
返回居住者为T;
}
因此,这里的代码按预期工作:
layers = new List<Layer>();
layers.Add(new Layer(this, "tiles"));
GetLayer("tiles").GetCellAt(5, 5).SetOccupant(new EnemyScientist(null, 5, 1, 6));
Enemy e = GetLayer("tiles").GetCellAt(5, 5).GetOccupant<Enemy>();
layers=newlist();
层。添加(新层(本“瓷砖”);
GetLayer(“tiles”).GetCellAt(5,5).SetOccuperator(新敌人科学家(null,5,1,6));
敌人e=GetLayer(“tiles”).GetCellAt(5,5).GetOccuptain();
虽然不是最好看的代码,地图系统将只用于这个游戏,所以我并不特别担心编写可重用的代码,大部分是功能代码。忽略一个事实,我刚刚在平铺层中插入了一个敌人,但我将添加一些廉价的检查(typeof),以确保我不会在某个地方把它搞砸。问题是
层和层没有任何可以将两者都强制转换的父类。最接近的是所有引用类型继承自的非常通用的对象
在这种情况下,一种常见的方法是,正如Lasse所建议的,定义一个它们都从中继承的公共接口:
interface ILayer
{
void CreateCells();
}
public class Layer<T> : ILayer
{
您需要考虑一种方法来设计ILayer
接口,使其不依赖于.NET Framework库中的泛型参数T
,实现方式如下:
class Program
{
static void Main(string[] args)
{
var layers = new List<ILayer<object>>();
layers.Add(new Layer<string>()); // It is covariance so we can only use reference types.
}
}
public interface ILayer<out T>
{
void CreateCells();
ICell<T>[] GetCells();
}
public class Layer<T> : ILayer<T>
{ }
public interface ICell<out T>
{ }
public class Cell<T> : ICell<T>
{ }
类程序
{
静态void Main(字符串[]参数)
{
var layers=新列表();
layers.Add(new Layer());//它是协方差,所以我们只能使用引用类型。
}
}
公共接口ILayer
{
void CreateCells();
ICell[]GetCells();
}
公共类层:ILayer
{ }
公共接口ICell
{ }
公共类单元格:ICell
{ }
新列表
可能吗?此外,C#还有通用约束—在文档中查找where
。您是否考虑过使用公共位实现接口?然后列表可以是ListI可以删除层的泛型类型,而改为层继承和接口是的,考虑到每个层都有相同的字段,这实际上可能是一个不错的选择。我将研究@LasseV.Karlsen建议的内容。您打算如何处理层列表?如果您正在对它们进行迭代,或者要应用一些常见的操作,那么似乎会有一些常见的行为,这是接口的理想候选者。最好先在静态类型语言中查找此类定义,否则您可能会发现您将要处理大量后续的强制转换。@Chris my layers将用于获取给定层上单元格中的任何内容。因此,如果你可以想象我想放置一座塔,首先我们抓取对象层,确保一座塔不存在,如果不存在,我们检查瓷砖层,确保“地形”可以容纳一座塔,如果是这样的话,请放置它,然后我们检查AI层,找出哪些实体在使用该磁贴进行导航时使用AI层并调整路径。谢谢,这看起来越来越像问题的最可能解决方案。请阅读您的编辑,有一个问题,该层需要类型T来确定每个单元格可以容纳的类型。因此,接口可能无法实际工作here@GibboLayer类仍然可以有一个泛型类型T
(请参见我使用的public class Layer:Layer{
)。简单地说,您的map类需要不知道T
w.r.T。它是如何存储和与层交互的。(例如,您可能需要让单元格
从单元格
继承,这样您的GetCells()
就可以返回列表
,而不是列表
)。很抱歉,我刚刚重新阅读了您的帖子,由于调用层的类和调用的接口,我搞混了LAyer@Gibbo不用担心现在,我已将接口重命名为ILayer
,以符合.NET命名约定。这将进行编译,但我不确定它最终是否会提供任何好处,并且它为运行时异常打开了可能性,否则不会发生。例如:var layers=new List;layers.Add(new Layer());ICell[]arr=layers[0].GetCells();arr[0]=new Cell();//runtine exception
out
不应被用作让编译器忽略类型安全性的方法。是的,对象的框在被分配后不能更改为其他类型。表示这是正常的:ICell Cell=new Cell();
layers = new List<Layer>();
layers.Add(new Layer(this, "tiles"));
GetLayer("tiles").GetCellAt(5, 5).SetOccupant(new EnemyScientist(null, 5, 1, 6));
Enemy e = GetLayer("tiles").GetCellAt(5, 5).GetOccupant<Enemy>();
interface ILayer
{
void CreateCells();
}
public class Layer<T> : ILayer
{
layers = new List<ILayer>();
layers.Add(new Layer<Tile>(this, "Tiles"));
class Program
{
static void Main(string[] args)
{
var layers = new List<ILayer<object>>();
layers.Add(new Layer<string>()); // It is covariance so we can only use reference types.
}
}
public interface ILayer<out T>
{
void CreateCells();
ICell<T>[] GetCells();
}
public class Layer<T> : ILayer<T>
{ }
public interface ICell<out T>
{ }
public class Cell<T> : ICell<T>
{ }