如何优化C#泛型使用,避免游戏属性系统重复类型声明?
优化游戏属性系统的C#泛型重复声明问题
你当前的属性系统设计中,RuntimeStat<T,Z>需要重复声明属性类和值类型(比如RuntimeStat<AttackPower, float>),确实存在冗余——因为AttackPower已经明确继承自Stat<float>,值类型可以被自动推断。以下是两种可行的优化方案:
方案1:静态工厂方法实现类型推断
通过添加静态工厂方法,让C#编译器自动推断泛型类型,无需手动重复声明值类型。这是保留类型安全前提下的最优方案。
修改RuntimeStat类
给RuntimeStat<T,Z>添加静态创建方法:
public class RuntimeStat<T, Z> where T : Stat<Z> { public int Level { get; private set; } public T Stat { get; } public Z Value => Stat.GetStat(Level); public RuntimeStat(T stat) { Stat = stat; } public void LevelUp() { Level++; } // 静态工厂方法,用于自动推断泛型类型 public static RuntimeStat<T, Z> Create(T stat) { return new RuntimeStat<T, Z>(stat); } }
或者创建独立的静态工厂类(调用更简洁):
public static class RuntimeStatFactory { public static RuntimeStat<T, Z> Create<T, Z>(T stat) where T : Stat<Z> { return new RuntimeStat<T, Z>(stat); } }
角色类中的简化使用
无论用哪种方式,创建实例时都可以省略泛型参数声明:
public class SomeCharacterClass { private RuntimeStat<AttackPower, float> _attackPower; public SomeCharacterClass() { // 方式1:使用RuntimeStat自身的静态方法 _attackPower = RuntimeStat<AttackPower, float>.Create(new AttackPower()); // 方式2:使用独立工厂类(更简洁) _attackPower = RuntimeStatFactory.Create(new AttackPower()); } public void Attack() { Debug.Log($"Attack for {_attackPower.Value} damage!"); } }
方案2:重构RuntimeStat为单泛型参数
如果希望彻底移除双泛型参数,可以通过非泛型接口+类型转换实现,但会牺牲一点类型安全(需要手动指定值类型)。
定义非泛型接口并修改Stat基类
// 非泛型接口,提供基础属性获取方法 public interface IStat { object GetStatValue(int level); } // 泛型Stat基类实现非泛型接口 public abstract class Stat<T> : IStat { public abstract T GetStat(int level); object IStat.GetStatValue(int level) { return GetStat(level); } }
重构RuntimeStat为单泛型参数
public class RuntimeStat<T> where T : IStat { public int Level { get; private set; } public T Stat { get; } public RuntimeStat(T stat) { Stat = stat; } public void LevelUp() { Level++; } // 泛型方法获取强类型属性值 public Z GetValue<Z>() { return (Z)Stat.GetStatValue(Level); } }
角色类中的使用
public class SomeCharacterClass { private RuntimeStat<AttackPower> _attackPower; public SomeCharacterClass() { _attackPower = new RuntimeStat<AttackPower>(new AttackPower()); } public void Attack() { // 需要手动指定值类型 float damage = _attackPower.GetValue<float>(); Debug.Log($"Attack for {damage} damage!"); } }
内容的提问来源于stack exchange,提问作者Arvin
相关产品推荐
相关产品推荐

