C#跨类数组问题:驱动类接收自定义数组遇阻及输出异常排查
问题解决与代码优化方案
1. 控制台输出P1CPSC3200.Formula+TypesForArrays[]的原因及解决
直接调用Console.WriteLine(Formulas)时,C#默认调用数组的ToString()方法,该方法返回数组的类型全名而非实际内容。要正确输出数组数据,有两种方案:
方案1:给TypesForArrays重写ToString()方法
public class TypesForArrays { public int numofOre = 2; public int numofStick = 1; public string Diam = "Diamonds"; public string Gold = "Gold Ingots"; public string Iron = "Iron Ingots"; public string Stick = "Sticks"; // 自定义输出格式 public override string ToString() { return $"矿石数量: {numofOre}, 木棍数量: {numofStick}, 资源类型: {Diam}/{Gold}/{Iron}/{Stick}"; } }
客户端遍历输出:
foreach(var item in formula1.Formulas) { Console.WriteLine(item); }
方案2:客户端直接遍历输出属性
foreach(var item in formula1.Formulas) { if(item != null) // 避免空引用异常 { Console.WriteLine($"矿石: {item.numofOre}, 木棍: {item.numofStick}, 钻石: {item.Diam}"); } }
2. 实现支持多种数据类型的配方数组
当前TypesForArrays是固定结构,无法灵活适配多种资源类型,可通过抽象基类+派生类实现扩展性:
// 通用资源基类 public abstract class Resource { public string Name { get; set; } public int Quantity { get; set; } } // 具体资源派生类 public class OreResource : Resource { } public class StickResource : Resource { } // Formula类中修改配方数组类型 public List<Resource>[] Formulas = new List<Resource>[1];
每个配方可自由组合资源,比如钻石剑配方:
Formulas[0] = new List<Resource> { new OreResource { Name = "Diamonds", Quantity = 2 }, new StickResource { Name = "Sticks", Quantity = 1 } };
3. 减轻客户端负载的优化
- 封装内部数据:将
Formulas设为私有,提供公共方法暴露配方信息,避免客户端直接操作内部数组:
private List<Resource>[] _formulas = new List<Resource>[1]; // 获取指定配方的方法 public List<Resource> GetRecipe(int index) { if(index >=0 && index < _formulas.Length) return _formulas[index]; return null; }
客户端仅需调用GetRecipe(0)获取配方,无需关心内部结构。
- 提取公共逻辑:
MakeDiamondSword和Apply逻辑高度重复,提取公共方法减少冗余:
// 计算制作结果的公共方法 private int CalculateCraftResult() { const int DiamondSword = 10; int chance = Percentage(); return chance switch { P75 => DiamondSword * P75, P110 => DiamondSword * P110, P100 => DiamondSword * P100, P0 => DiamondSword * P0, _ => -1 }; } // 制作方法(扣除资源) public int MakeDiamondSword() { if (Diamond > 1 && Stick > 0) { Diamond -= 2; Stick -= 1; Proficiency += 1; return CalculateCraftResult(); } return -1; } // 模拟制作(不扣除资源) public int Apply() { if (Diamond > 1 && Stick > 0) { return CalculateCraftResult(); } return -1; }
4. 配方功能的完善建议
- 分离配方数据与逻辑:将每种物品的配方(资源类型、数量)存入
Formulas数组,制作时动态读取配方扣除资源,避免硬编码资源数值。 - 初始化配方数组:当前
Formulas是长度为1的空数组,需在构造函数中初始化元素,避免空引用异常:
public Formula(int Dia, int Sti) { Diamond = Dia; Stick = Sti; // 初始化配方元素 Formulas[0] = new TypesForArrays(); }
内容的提问来源于stack exchange,提问作者bchennnn
相关产品推荐
相关产品推荐

