通用方法如何返回所有类型T

时间:2012-08-28 02:43:15

标签: c# generics

说我有以下代码:

public class Pond
{
  public List<Frog> Frogs { get; set; }
  public List<MudSkipper> MudSkippers { get; set; }
  public List<Eel> Eels { get; set; }
}

public class Frog: IAquaticLife
{

}



public class MudSkipper: IAquaticLife
{

}



public class Eel: IAquaticLife
{

}

现在我想编写一个通用方法,用于某个池塘返回这些类型的列表:

public IEnumerable<T> GetByPond<T>(int pondId) where T : IAquaticLife
{
   return Uow.GetByID<Pond>(pondId).Eels;
}

好的,所以我在那里将返回那个池塘里的所有鳗鱼。我想要做的是返回所有的T。

所以,如果我打电话给GetByPond<MudSkipper>(1)那将会返回所有的mudskippers。

任何人都知道怎么做?

3 个答案:

答案 0 :(得分:5)

这样的东西
public IEnumerable<T> GetByPond<T>(int pondId) where T : IAquaticLife
{
   return from t in Uow.GetByID<Pond>(pondId).AquaticLife() 
          where (typeof(t) == typeof(T)) select t;
}

或简单地(使用@DStanley在更改答案之前指出的方法)

public IEnumerable<T> GetByPond<T>(int pondId) where T : IAquaticLife
{
   return Uow.GetByID<Pond>(pondId).AquaticLife().OfType<T>();
}

这需要 Uow.GetByID(int id)来返回特定池塘中实现 IAquaticLife 的所有类型的生物。但另一种方法是,您将 IAquaticLife 的各种实现者的知识硬编码到您的通用方法中。这不是一个好主意。

<强>更新

目前 Pond Eels Mudskippers 等单独的集合。如果你想添加更多实现<的东西,那就变得脆弱了em> IAquaticLife 随着你的代码的发展,因为你必须改变 Pond 和上面的通用方法。

我建议您不要使用单独的方法来处理每种类型的水生生物,而是使用一种方法返回池塘中实现 IAquaticLife 的所有方法,例如

public class Pond
{
    public IEnumerable<IAquaticLife> AquaticLife() { ... }
}

我已经用这个假设更新了上面的代码。

任何拥有Pond实例但想要获得的人都可以这样做:

var eels = pond.AquaticLife().OfType<Eels>();

答案 1 :(得分:2)

试试这个:

return Uow.GetByID<Pond>(pondId).OfType<T>();

<击>

修改

由于您已将集合放在单独的属性中,因此可以使用switch块根据类型返回正确的属性,或使用反射根据类型名称获取属性。

基于您的要求的更好的设计是拥有一个私有的List<IAquaticLife>来存储所有的生物而不是单独的属性,但我会假设您现在不能这样做。

交换机的一个例子是:

public IEnumerable<T> GetByPond<T>(int pondId) where T : IAquaticLife
{
    switch(typeof(T))
    {
        case typeof(Eel):
            return Uow.GetByID<Pond>(pondId).Eels;
        //etc.
        default:
            throw new ApplicationException(string.Format("No property of type {0} found",typeof(T).Name));
    }
}

答案 2 :(得分:-1)

public Pond GetByPond(int pondId)
{
    return Uow.GetByID<Pond>(pondId);
}

如果你想要你的青蛙,请执行:

var frogs = xxx.GetByPond(1).Frogs;

如果你想要你的MudSkippers,请执行:

var mudSkippers = xxx.GetByPond(1).MudSkippers;

等等。

如果您可以致电GetByPond<Frog>(1),则可以致电GetByPond(1).Frogs

如果在任何情况下你都不知道T,你需要创建所有这些的集合并按类型过滤它们。如果您有中间子类型,这也很有用:

public IEnumerable<T> GetByPond<T>(int pondId) where T : IAquaticLife
{
    var pond = Uow.GetByID<Pond>(pondId);
    var life = pond.Frogs.Union(pond.Eels).Union(pond.MudSkippers);
    return life.OfType<T>();
}

但是你正在连接集合只是为了过滤它们。