有时我想要任何“T”时我应该使用泛型吗?

时间:2013-02-11 19:02:16

标签: c# generics

我正在制作一个关于工厂的游戏。工厂里有箱子搬进去。有时会有包含Crates包含Items的Depots,并且工作人员需要在Crates中查找某些类型的Items(例如,worker可能会调用一个函数来询问"在任何Depots中是否有任何Crates包含食物?",如果是这样的话,他会去拿它并把它移到某个地方。

似乎非常有用的定义" Crate"和家具"使用泛型的类(从中继承Depot)来指定它们包含的对象类型。下面是我的Crate类和我的Furniture类的片段,然后是我正在努力解决的Depot类:

public class Crate<I> : Item 
    where I : Item
{
}

public abstract class Furniture<I>
    where I : Item
{
}

public class Depot : Furniture<Crate<???>>
{
    //...
}

泛型在这里很有用,因为我可以编写如下搜索方法:

public I FindItem<I,F>
 where I:Item
 where F:Furniture<I>
{
    //pseudocode

    //foreach (furniture f in the factory);
    //if (f is F) foreach (I i in f)
    //if (i.IsAvailable) return i;

    //return null;
}

现在,我的问题是,与大多数其他家具不同,Depots可以将Crate与其中的任何东西一起使用(例如Crate of Food和Crates of raw materials)。但是我不能只指定Crate(Item),因为它会搞乱我的搜索算法 - 寻找Crates of Food会返回null,因为它只包含Crates of Items。

我应该为Crate保留泛型但是为StorageFurniture废弃它们,并使我的搜索算法稍长一些(即搜索所有的Furniture而不仅仅是那些包含正确类型的项目的Furniture),或者是否有办法绕过这个问题?

2 个答案:

答案 0 :(得分:1)

考虑为Crate-able对象创建根类或接口:

public class Crate<I> : Item 
    where I : Item
{
    private int capacity;
    private List<I> contents;
    //... and so on
}

public interface ICrateable{
// define common features such as name, ID, description etc here
}

public class Shirt: ICrateable{
// implement interface
}


public class DepotSlot : StorageFurniture<Crate<ICrateable>>
{
    // now you can add any Crate<XYZ> here
}

如果您正在处理Crate-s,那么只有你要做的常见事情才有意义 - 打开它们,关闭它们,在它们上面贴上标签,丢弃它们,装上卡车,卸下它们等等。所有这些常见功能都可以在根(抽象?)类或接口中进行抽象。

如果您没有对包装箱进行任何预定义操作,您可以将它们oject放在一边并放弃仿制品

答案 1 :(得分:0)

如果您的游戏将在您的商店中“自包含”,那么更改基本类型并重新编译所有内容将不会是一个过度的负担,我建议在您的基础中使用许多虚拟方法可能是有利的“ GameObject“类型,并且有一个字段可以指示(通过”标记“枚举)哪些方法将对给定对象执行某些操作。如果有一个游戏对象列表,并且希望对该列表中与该动作相关的所有对象执行某些操作(例如炸弹爆炸并且想要“破坏”爆炸范围内的所有可破坏物品),则无条件地更快调用虚方法对于所有对象都是通用的 - 甚至是那些无用的对象 - 而不是测试每个对象是否实现了接口并在对象上调用该接口(如果是这样)。

让字段指示哪些类型的调用与对象相关可能在某些情况下通过允许系统在虚拟方法调用之前避免做某些工作来提高性能。例如,如果测试字段将显示对象不会对TakeBombDamage调用执行任何操作,则无需浪费时间计算对象将要承受的损坏量。

如果采用向基类添加虚方法的方法来支持某些但不是所有对象中存在的能力,则可以最小化执行运行时类型转换的需要。这将反过来减少对泛型的需求。在基类的更改很麻烦的情况下,“kitchen-sink基类”方法并不好,但在性能很重要的情况下可能会有所帮助,特别是对于存在合理默认值的行为(例如,如果是“FlashingStrobe”游戏对象在附近的物体上调用NoticeFlashingStrobe,不关心闪烁频闪的物体在这种方法中可能明显无效。)