如何生成指定类(如BAnimal)的所有实例列表?未赋值类实例如何处理?
问题解答
1. 如何自动维护特定类的所有实例列表
通用开发场景下完全可以实现该需求,核心思路是在类内部定义静态集合存储所有实例,在构造函数执行时自动将当前实例加入集合即可,示例实现如下:
public class BAnimal { // 静态列表存储所有BAnimal实例 public static List<BAnimal> AllInstances { get; private set; } = new List<BAnimal>(); // 多线程场景建议加锁保证线程安全 private static object _lockObj = new object(); public string Name { get; set; } public string Tag { get; set; } public BAnimal(string name, string tag) { Name = name; Tag = tag; // 构造实例时自动加入全局列表 lock(_lockObj) { AllInstances.Add(this); } } // 如果有销毁实例的需求,需要补充移除逻辑避免内存泄漏 public void Destroy() { lock(_lockObj) { AllInstances.Remove(this); } } }
使用时不需要手动维护列表,所有实例都会被自动收集:
// 两种创建方式的实例都会自动加入全局列表 var FennecFox = new BAnimal("Fennec Fox", "FennecFox"); new BAnimal("Badger", "Badger"); // 直接读取静态属性即可拿到所有实例 var allAnimals = BAnimal.AllInstances;
如果担心静态列表长期持有实例导致无法被GC回收,可以将静态集合改为存储弱引用:
// 定义弱引用集合 public static List<WeakReference<BAnimal>> AllInstances { get; private set; } = new List<WeakReference<BAnimal>>(); // 构造函数中改为存储弱引用 AllInstances.Add(new WeakReference<BAnimal>(this)); // 读取时先判断实例是否存活 foreach(var weakRef in AllInstances) { if(weakRef.TryGetTarget(out var animal)) { // 对存活实例进行操作 } }
2. 无变量接收的实例能否被后续操作
默认情况下,new BAnimal("Badger", "Badger");这种写法没有任何引用指向创建的实例,你后续无法直接访问该实例,GC会在合适的时机回收该对象的内存。IDE提示你加丢弃修饰符_ = new BAnimal("Badger", "Badger");是为了明确你是主动放弃该实例的引用,避免误报“创建的对象从未被使用”的警告。
但如果用上文提到的静态实例列表方案,即使你没有用变量接收实例,实例已经被添加到静态列表中持有了强引用,你后续可以直接从BAnimal.AllInstances中获取到该实例进行操作,刚好可以满足你“直接创建实例后统一生成所有实例列表”的需求。
内容的提问来源于stack exchange,提问作者David Campbell
相关产品推荐
相关产品推荐

