关于移除对象的第二个引用的技术咨询(附代码示例)
Looking at your code, the issue is that each FactorizableObject has two strong references: one stored in the Factory's _collected list, and another in UsingClass1's myObject field. To eliminate the second reference, we have two primary approaches depending on your needs.
Approach 1: Use the Factory as a Central Mediator (No Direct Reference in UsingClass)
This approach removes the direct reference in UsingClass1 entirely. Instead, we store a unique identifier for the object and retrieve it from the Factory whenever we need to interact with it. This is ideal if you want the Factory to maintain full control over object lifecycle.
Step 1: Add a Unique Identifier to FactorizableObject
First, give each object a unique ID so we can look it up later:
class FactorizableObject { public Guid Id { get; } private someParams _params; public FactorizableObject(someParams dontMatter) { Id = Guid.NewGuid(); _params = dontMatter; // Initialize other members as needed } // Example method to demonstrate object functionality public void PerformAction() { // Do something with _params } }
Step 2: Update Factory to Track Objects by ID
Replace the List with a Dictionary for efficient lookups, and return the object's ID instead of the object itself:
class Factory { private Dictionary<Guid, FactorizableObject> _collected = new Dictionary<Guid, FactorizableObject>(); public Guid CreateObject(someParams dontMatter) { var newObject = new FactorizableObject(dontMatter); _collected.Add(newObject.Id, newObject); return newObject.Id; // Return ID instead of the object instance } // Retrieve object by ID (returns null if not found) public FactorizableObject GetObjectById(Guid objectId) { _collected.TryGetValue(objectId, out var targetObject); return targetObject; } // Optional: Remove object from Factory's collection public bool RemoveObject(Guid objectId) { return _collected.Remove(objectId); } public void DoSomethingWithCollectedObjects() { foreach (var obj in _collected.Values) { // Process each object obj.PerformAction(); } } }
Step 3: Modify UsingClass1 to Use the ID
Instead of storing the object directly, store its ID and fetch it from the Factory when needed:
class UsingClass1 { private Guid _objectId; private readonly Factory _factory; // Inject the Factory dependency (better practice than static access) public UsingClass1(Factory factory) { _factory = factory; _objectId = factory.CreateObject(new someParams()); // Pass your params here } public void UseMyObject() { var myObject = _factory.GetObjectById(_objectId); if (myObject != null) { // Interact with the object myObject.PerformAction(); } else { // Handle case where object was removed from the Factory Console.WriteLine("Object no longer exists in Factory."); } } }
Approach 2: Use Weak References (Keep Access Without Strong Reference)
If you still need UsingClass1 to access the object but don't want its reference to prevent garbage collection (or avoid adding an extra strong reference), use WeakReference<T>. This way, the only strong reference remains in the Factory's collection.
Modified UsingClass1 with WeakReference
class UsingClass1 { private readonly WeakReference<FactorizableObject> _weakObjectRef; public UsingClass1() { var newObject = Factory.CreateObject(new someParams()); _weakObjectRef = new WeakReference<FactorizableObject>(newObject); } public void UseMyObject() { if (_weakObjectRef.TryGetTarget(out var myObject)) { // Object is still alive in the Factory's collection myObject.PerformAction(); } else { // Object has been garbage collected or removed from Factory Console.WriteLine("Object is no longer available."); } } }
Note: The object will only be garbage collected if the Factory removes it from _collected (since that's the only strong reference). This approach is useful when you want temporary access without prolonging the object's lifecycle unnecessarily.
Key Notes:
- Approach 1 is better for strict lifecycle management (Factory controls when objects exist).
- Approach 2 is useful for scenarios where you need occasional access but don't want to tie the object's lifespan to
UsingClass1.
内容的提问来源于stack exchange,提问作者Tobias Neis

