如何创建子类列表并在常规循环中获取其Salary属性
如何正确获取子类的Salary属性
问题场景
你有带Rank属性的Worker基类,以及带Salary属性的Manager、Marketer子类,基类无Salary属性。需要创建仅包含这些子类的列表,并通过循环获取所有元素的Salary属性。
现有类定义
public class Worker { public int Rank { get; set; } public Worker(int rank) { Rank = rank; } } public class Manager : Worker { public Manager(int rank) : base(rank) { } public static int BaseSalary = 50000; public int Salary { get { return BaseSalary * Rank; } } } public class Marketer : Worker { public Marketer(int rank) : base(rank) { } public static int BaseSalary = 20000; public int Salary { get { return BaseSalary * Rank; } } }
出错的循环代码
List<Worker> List = new List<Worker>(); var Manager = new Manager(3); List.Add(Manager); var Marketer = new Marketer(2); List.Add(Marketer); for (int i = 0; i < List.Count; i++) { Console.WriteLine(List[0].Salary); }
问题原因
- 编译类型限制:
List<Worker>中的元素编译时被视为Worker类型,而基类Worker没有Salary属性,直接访问会报错。 - 循环索引错误:循环中始终访问
List[0],无法遍历所有元素。
解决方案
方案一:定义统一接口(推荐)
创建包含Salary属性的接口,让子类实现该接口,列表声明为接口类型即可直接访问Salary。
// 定义接口 public interface IPaidWorker { int Salary { get; } } // 修改子类实现接口 public class Worker { public int Rank { get; set; } public Worker(int rank) { Rank = rank; } } public class Manager : Worker, IPaidWorker { public Manager(int rank) : base(rank) { } public static int BaseSalary = 50000; public int Salary => BaseSalary * Rank; } public class Marketer : Worker, IPaidWorker { public Marketer(int rank) : base(rank) { } public static int BaseSalary = 20000; public int Salary => BaseSalary * Rank; } // 修正后的列表和循环代码 List<IPaidWorker> paidWorkers = new List<IPaidWorker>(); paidWorkers.Add(new Manager(3)); paidWorkers.Add(new Marketer(2)); for (int i = 0; i < paidWorkers.Count; i++) { Console.WriteLine(paidWorkers[i].Salary); }
方案二:使用抽象类
如果Worker不需要实例化,可改为抽象类并定义抽象Salary属性,让子类实现。
// 修改Worker为抽象类 public abstract class Worker { public int Rank { get; set; } public Worker(int rank) { Rank = rank; } // 定义抽象Salary属性 public abstract int Salary { get; } } // 子类实现Salary属性 public class Manager : Worker { public Manager(int rank) : base(rank) { } public static int BaseSalary = 50000; public override int Salary => BaseSalary * Rank; } public class Marketer : Worker { public Marketer(int rank) : base(rank) { } public static int BaseSalary = 20000; public override int Salary => BaseSalary * Rank; } // 列表和循环代码 List<Worker> workers = new List<Worker>(); workers.Add(new Manager(3)); workers.Add(new Marketer(2)); for (int i = 0; i < workers.Count; i++) { Console.WriteLine(workers[i].Salary); }
方案三:类型转换(不推荐)
若不想修改类结构,可在循环中判断并转换类型,但这种方式扩展性差,破坏面向对象封装性。
List<Worker> workers = new List<Worker>(); workers.Add(new Manager(3)); workers.Add(new Marketer(2)); for (int i = 0; i < workers.Count; i++) { if (workers[i] is Manager manager) { Console.WriteLine(manager.Salary); } else if (workers[i] is Marketer marketer) { Console.WriteLine(marketer.Salary); } }
关键修改点总结
- 确保列表元素的编译类型包含
Salary属性(通过接口或抽象类实现) - 循环中使用
i作为索引访问对应元素,而非固定的0
内容的提问来源于stack exchange,提问作者Battlecruiser Games
相关产品推荐
相关产品推荐

