这篇文章包含很多代码,但如果您能花一些时间阅读和理解它,我将非常感激......并希望能找到一个解决方案
假设我正在构建一个网络游戏,其中需要绘制实体,并相应地从服务器更新其中一些实体。
Drawable
类负责在屏幕上绘制实体:
class Drawable
{
public int ID { get; set; } // I put the ID here instead of having another
// class that Drawable derives from, as to not
// further complicate the example code.
public void Draw() { }
}
从服务器接收的数据实现 IData
与每个混凝土IData
持有不同的属性(property)。假设我们有以下数据 Player
和Enemy
将收到:
interface IData
{
int ID { get; set; }
}
class PlayerData : IData
{
public int ID { get; set; }
public string Name { get; set; }
}
class EnemyData : IData
{
public int ID { get; set; }
public int Damage { get; set; }
}
应该可以从服务器更新的游戏实体实现 IUpdateable<T>
哪里T
是 IData
:
interface IUpdateable<T> where T : IData
{
void Update(T data);
}
我们的实体是 Drawable
和Updateable
:
class Enemy : Drawable, IUpdateable<EnemyData>
{
public void Update(EnemyData data) { }
}
class Player : Drawable, IUpdateable<PlayerData>
{
public void Update(PlayerData data) {}
}
这就是游戏的基本结构。
现在,我需要存储 Dictionary
其中Drawable
和Updateable
对象,存储 Drawable
的 ID 作为键和一个包含 Drawable
的复杂对象和Updateable
物体及其远程具体IData
:
class DataHolder<T, T1> where T:Drawable, IUpdateable<T1> where T1:IData
{
public T Entity{ get; set;}
public IData Data{ get; set;}
public DataHolder(T entity, IData data)
{
Entity = entity;
Data = data;
}
}
举个例子,假设我目前有以下实体:
var p1 = new Player();
var p1Data = new PlayerData();
var e1 = new Enemy();
var e1Data = new EnemyData();
var playerData = new DataHolder<Player, PlayerData>(p1, p1Data);
var enemyData = new DataHolder<Enemy, EnemyData>(e1, e1Data);
我现在需要一个Dictionary
它将实体的 ID 作为键( p1.ID
和 e1.ID
)及其 DataHolder
( playerData
和 enemyData
)及其值。
类似于以下内容(下面的代码仅显示了我想要执行的操作,因此它不会编译):
Dictionary<int, DataHolder> list = new Dictionary<int, DataHolder>();
list.Add(p1.ID, playerData);
list.Add(e1.ID, enemyData);
如何构建这样的字典?
[更新]
关于使用,我将需要能够执行以下操作:
foreach (var value in list.Values)
{
var entity = value.Entity;
entity.Update(value.Data);
}
我也尝试过改变 DataHolder
的设计到以下内容:
class DataHolder<T> where T:Drawable, IUpdateable<IData>
{
public T Entity{ get; set;}
public IData Data{ get; set;}
public DataHolder(T entity, IData data)
{
Entity = entity;
Data = data;
}
}
然后我尝试了类似以下的操作:
var playerData = new DataHolder<Player>(p1, p1Data); //error
但这会引发编译时错误:
The type 'Player' must be convertible to 'IUpdateable<IData>' in order to use it as parameter 'T' in the generic class 'DataHolder<T>'
这个抛出的原因是什么? Player
实现IUpdateable<PlayerData>
和PlayerData
实现IData
。这是方差问题吗?有什么办法可以解决这个问题吗?
最佳答案
使您的 DataHolder
类实现或继承非泛型类或接口(interface),然后创建该(非泛型)类型的字典。
关于c# - C#中涉及集合、泛型和接口(interface)的设计问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3346263/