C#,访问类中不同列表的通用方法

C#,访问类中不同列表的通用方法,c#,generics,C#,Generics,我有一个由3个不同链表组成的类(用于在我正在处理的游戏中保存实体)。这些列表都是具有相同基类型的对象,但出于处理原因,我将它们分开。请注意,IEntity、IOObject和IUndead都是从IEntity继承的 public class EntityBucket { public LinkedList<IEntity> undeadEntities; public LinkedList<IEntity> objects; public Link

我有一个由3个不同链表组成的类(用于在我正在处理的游戏中保存实体)。这些列表都是具有相同基类型的对象,但出于处理原因,我将它们分开。请注意,IEntity、IOObject和IUndead都是从IEntity继承的

public class EntityBucket
{
    public LinkedList<IEntity> undeadEntities;
    public LinkedList<IEntity> objects;
    public LinkedList<IEntity> livingEntities;

    public EntityBucket()
    {
        undeadEntities = new LinkedList<IEntity>();
        objects = new LinkedList<IEntity>();
        livingEntities = new LinkedList<IEntity>();
    }

    public LinkedList<IEntity> GetList(IObject e)
    {
        return objects;
    }

    public LinkedList<IEntity> GetList(IUndead e)
    {
        return undeadEntities;
    }

    public LinkedList<IEntity> GetList(ILiving e)
    {
        return livingEntities;
    }

}
公共类EntityBucket
{
公共链接列表十一项;
公共链接列表对象;
公共社交网站livingEntities;
公共实体bucket()
{
十一项=新建链接列表();
对象=新的LinkedList();
livingEntities=新链接列表();
}
公共链接列表GetList(IOObject e)
{
归还物品;
}
公共链接列表获取列表(IUndead e)
{
返回不定项;
}
公共链接列表GetList(ILiving e)
{
回归活力;
}
}
我有3种方法来检索每个列表,目前基于它们的参数。有3个就可以了,因为我知道每个列表都会以某种方式需要自己的访问器。不过,传递一个实例化对象并不理想,因为我可能想在某个地方检索一个列表,而手头没有类似类型的对象。请注意,这里的对象甚至没有在GetList方法中使用,它们只是用于确定要使用的版本。下面是一个示例,其中我手头有一个实例化对象:

public void Delete(IUndead e, World world)
{

     .....
     LinkedList<IEntity> list = buckets[k].GetList(e);
     .....
}
public void Delete(IUndead e,World)
{
.....
LinkedList=bucket[k].GetList(e);
.....
}
我不喜欢这个当前的实现,因为我可能并不总是手头有一个实例化的对象(例如在呈现实体时)。我想一般地做,但我不确定我想做的事情是否可行。有了这个,我还需要3个Delete方法(以及3个其他方法,比如add等等)——每种类型一个,IUndead、ioobject和ILiving。我只是觉得这样做是不对的

我将根据要求发布我到目前为止尝试做的事情,但我的泛型相当糟糕,我觉得任何人阅读这篇文章都是一种浪费


最后,性能非常重要。我不是过早地优化,我是后期优化,因为我已经有了工作代码,但需要它更快。getlist方法将经常被调用,我希望避免任何显式的类型检查。

因此您需要一个更好的接口,因为正如您所说,将不必要的对象传递给
getlist
仅仅是为了确定其类型没有什么意义

你可以这样做:

public List<IEntity> GetList<T>() : where T:IEntity
{
    if(typeof(T)==typeof(IUndead)) return undedEntities;
    // and so on
}
public List GetList():其中T:ienty
{
如果(typeof(T)=typeof(IUndead))返回不确定项;
//等等
}
您必须这样调用它:
GetList()

我认为enum在这里是一个更好的主意:

enum EntityTypes { Undead, Alive, Object };
public List<IEntity> GetList(EntityTypes entityType) { ... }
enum EntityTypes{Undead,Alive,Object};
公共列表GetList(EntityTypes entityType){…}
它更干净,对我来说更有意义


编辑:使用泛型实际上并没有那么简单。有人可以调用GetList a
Zombie
type,它实现了IUndead,然后您必须检查接口实现。有人甚至可以给你一个
LiveZombie
,它实现了IUndead和IAlive。一定要使用枚举。

下面的例子怎么样

public LinkedList<IEntity> GetList(Type type) {
    if (typeof(IUndead).IsAssignableFrom(type)) return undeadEntities;
    if (typeof(ILiving).IsAssignableFrom(type)) return livingEntities;
    if (typeof(IObject).IsAssignableFrom(type)) return objects;
}
相同类型的逻辑可以在deletes、add和其他方法中实现,并且不需要对象的具体实例来访问它们

IsAssignableFrom
逻辑可以很好地处理子类化(也就是说,您可以有一个
CatZombie
,它派生自
Zombie
,它实现了
IUndead
,这仍然可以工作)。这意味着您仍然只需创建一个Delete方法,如下所示:

public void Delete(IEntity e, World world) {
    if (typeof(IUndead).IsAssignableFrom(type)) undeadEntities.Remove(e);
    if (typeof(ILiving).IsAssignableFrom(type)) livingEntities.Remove(e);
    if (typeof(IObject).IsAssignableFrom(type)) objects.Remove(e);
}

编辑:我注意到你对zmbq关于绩效的回答的评论;这绝对不是很快。如果需要高性能,请使用枚举样式的方法。您的代码将更加冗长,需要更多的维护,但您将获得更好的性能。

在我看来,您可以实现一个字典 已命名LinkedList的,并引用它们 按名称或枚举

这样添加或删除列表只是一个简单的过程
实现问题,并且没有单独的类需要处理。

更好的接口实现如何

public class EntityBucket
{
  public LinkedList<IEntity> Entities;

  public IEnumerable<T> GetEntities<T>() where T : IEntity
  {
    return Entities.OfType<T>();
  }

}


List<IUndead> myBrainFinders = bucket.GetEntities<IUndead>().ToList();
公共类EntityBucket
{
公共链接列表实体;
public IEnumerable GetEntities(),其中T:IEntity
{
返回实体;
}
}
列出myBrainFinders=bucket.GetEntities().ToList();

使用此实现,调用方最好将每个项添加到正确的列表中。这是您最初实现的一个要求,所以我认为这没有问题

public class EntityBucket
{
  Dictionary<Type, List<IEntity>> entities = new Dictionary<Type, List<IEntity>>();

  public void Add<T>(T item) where T : IEntity
  {
    Type tType = typeof(T);
    if (!entities.ContainsKey(tType))
    {
      entities.Add(tType, new List<IEntity>());
    }
    entities[tType].Add(item);
  }

  public List<T> GetList<T>() where T : IEntity
  {
    Type tType = typeof(T);
    if (!entities.ContainsKey(tType))
    {
      return new List<T>();
    }
    return entities[tType].Cast<T>().ToList();
  }

  public List<IEntity> GetAll()
  {
    return entities.SelectMany(kvp => kvp.Value)
      .Distinct() //to remove items added multiple times, or to multiple lists
      .ToList();
  }

}
公共类EntityBucket
{
字典实体=新字典();
公共无效添加(T项),其中T:Entity
{
类型tType=类型(T);
如果(!entities.ContainsKey(tType))
{
添加(tType,newlist());
}
实体[t类型].添加(项);
}
public List GetList(),其中T:IEntity
{
类型tType=类型(T);
如果(!entities.ContainsKey(tType))
{
返回新列表();
}
返回实体[tType].Cast().ToList();
}
公共列表GetAll()
{
返回entities.SelectMany(kvp=>kvp.Value)
.Distinct()//删除多次添加或添加到多个列表的项目
.ToList();
}
}

如果没有实际使用,
GetList
方法中的参数是什么?看起来你可以将列表作为属性而不是方法公开。我以前就是这样做的,但是正如我所说的,我必须有3个版本的每个方法来访问这些列表。我不想要3个,我想要一个通用版本。这不能通过将列表作为属性显式调用来完成。列表本身需要以通用的方式检索。要选择的正确列表必须是dete
public class EntityBucket
{
  Dictionary<Type, List<IEntity>> entities = new Dictionary<Type, List<IEntity>>();

  public void Add<T>(T item) where T : IEntity
  {
    Type tType = typeof(T);
    if (!entities.ContainsKey(tType))
    {
      entities.Add(tType, new List<IEntity>());
    }
    entities[tType].Add(item);
  }

  public List<T> GetList<T>() where T : IEntity
  {
    Type tType = typeof(T);
    if (!entities.ContainsKey(tType))
    {
      return new List<T>();
    }
    return entities[tType].Cast<T>().ToList();
  }

  public List<IEntity> GetAll()
  {
    return entities.SelectMany(kvp => kvp.Value)
      .Distinct() //to remove items added multiple times, or to multiple lists
      .ToList();
  }

}