使用泛型与基类时重载方法

时间:2017-07-10 14:13:24

标签: c# generics

我有以下课程:

public abstract class Gear<T> : ScriptableObject, IGear { ... }

public class Armor : Gear<ArmorStatsLevel> { ... }

public class Weapon : Gear<WeaponStatsLevel> { ... }

现在我有以下方法列出我的实例:

public abstract class WidgetListArmor {

    public void ActionSelected(Armor gear) {
        if (...) GameSession.Equip(gear);
    }
}

public abstract class WidgetListWeapon {

    public void ActionSelected(Weapon gear) {
        if (...) GameSession.Equip(gear);
    }
}

因为这有点多余,我想把它全部移到一个基地:

public abstract class WidgetListGear<T> : MonoBehaviour {

    public void ActionSelected(T gear) {
        if (...) GameSession.Equip(gear);
    }
}

public class WidgetListArmors  : WidgetListGear<Armor> { ... }

public class WidgetListWeapons : WidgetListGear<Weapon> { ... }

虽然这看起来更干净,但我现在遇到了一个新问题。由于T是通用的,GameSession.Equip无法重载gear

我选择了一个糟糕的模式来组织我的代码吗?我是否遗漏了Generics允许我进行此操作的内容?

更新

以下是GameSession签名:

public class GameSession {
    public static bool Equip(Armor armor);
    public static bool Equip(Weapon weapon);
}

2 个答案:

答案 0 :(得分:3)

WeaponArmor实现名为IGear的界面,例如:

public interface IGear 
{ }

public class Weapon : IGear
{
    //snip
}

public class Armor : IGear
{
    //snip
}

将通用类型约束为IGear

public abstract class WidgetListGear<T> : MonoBehaviour
    where T : IGear
{

    public void ActionSelected(T gear) {
        if (...) GameSession.Equip(gear);
    }
}

GameSession.EquipIGear作为参数类型。

答案 1 :(得分:1)

您正在寻找的是动态调度。我建议你尝试以下方法:

GameSession.Equip((dynamic)gear);

但是,我不认为这是最好的主意,因为你已经尝试在类型系统中对游戏规则进行编码,现在你正在运行时启动一个迷你编译器来为你执行调度。

我想指出Eric Lippert关于这个问题的articles。看起来你和他描述的内容有类似的问题。

Part 4描述了我提供的动态方法及其缺点。 Part 5提供了一种完全不同的方法。总的来说,我强烈建议阅读每个部分。