说明
我正在尝试为我的游戏编写效果(增益/减益)。以下是我想要构建的内容:
类EffectsManager
包含所有活动效果。像HealthController
这样的类会查询它以获取与健康相关的效果,即实现IHealthEffect
接口的效果,并返回仅包含此类效果的列表。
尝试的解决方案
内部EffectsManager
:
public List<T> GetEffects<T>() {
List<T> effects = new List<T>();
foreach (ActiveEffect activeEffect in activeEffects) {
// ActiveEffect is just a wrapper for Effect that houses duration, time elapsed, etc.
// I only need to return the Effect itself, which houses the logic.
Effect effect = activeEffect.GetEffect();
if (effect is T) {
effects.Add((T)effect);
}
}
return effects;
}
然后,调用方脚本将写入:
List<IHealthEffect> healthEffects = effectsManager.GetEffects<IHealthEffect>();
问题
无法将类型"效果"转换为"T">
在effects.Add((T)effect);
.
类似问题
无法将类型"Int"隐式转换为"T">
但就我而言,我不是在做隐式的,而是在做明确的转换。为什么编译器不让我继续,我应该使用Convert.ChangeType()
- 正如那里建议的那样 - 无论如何?
更多信息
Effect
只是一个只有 1 个成员的抽象类:public int priority;
。
由于效果可能会影响多个属性,例如生命值和法力值,因此我决定使用要求实现者编写特定方法的接口,例如:void Execute(HealthController healthController);
。
你来了:
if (effect is T typed) {
effects.Add(typed);
}
至于为什么:你需要在中间投object
:(T)(object)effect
但就我而言,我不是在做隐式的,而是在做显式的强制转换。
Effect
和T
是不相关的,因此编译器将尝试转换而不是强制转换,并且显然也没有在类型之间定义转换,因此会出现错误。
正如 Marc 所建议的,您可以充分利用模式匹配:
if (effect is T t) {
effects.Add(t);
}
但是,如果您的代码与发布的内容完全相同,则可以完全通过 LINQ 实现此目的:
var healthEffects = activeEffects.Select(x => x.GetEffect()).OfType<IHealthEffect>();