Suggestions on how to avoid deleting an object twice

I have a list of disposable items that I add to a collection that already contains several disposable items. I am completing the code in an attempt ... to finally block so that if an exception is thrown when copying elements from the list to the collection, all objects in the list are deleted correctly:

private static void LoadMenuItems(ApplicationMenu parent) { List<ApplicationMenuItem> items = null; try { items = DataContext.GetMenuItems(parent.Id); foreach (var item in items) { parent.Items.Add(item); } items = null; } finally { if (items != null) { foreach (var item in items) { item.Dispose(); } } } } 

If an exception occurs after adding several objects to the collection, I will have a situation where the collection contains some objects. This can cause those located objects to be deleted again in the next attempt ... catch block:

 try { // Assume that menu.Items contains some items prior // to the call to LoadMenuItems. LoadMenuItems(menu); } catch { // The Dispose() iterates through menu.Items calling // Dispose() on each. menu.Dispose(); } 

So, I am looking for possible solutions to stop Dispose () being called twice. I have a solution, but I thought I would give it to the community to find out if there are any alternatives.

+4
source share
2 answers

This may cause the remaining objects to be deleted again.

Which should be good. The contract for Dispose () is very specific: it should be safely called several times.


But another way to get rid of it:

Analyzing your logic, I would say that the finally part is superfluous, maybe the analyzer also thinks so. You really solve the same problem twice.

+5
source

In most cases, when you can worry about “accidentally” deleting an object several times because there is confusion about who “owns” the object in question, and such confusion is likely to create other problems in addition to re-deleting. While it is possible to avoid the problem of multiple destruction causing problems because the deletion method uses the flag, so the second disposal attempt will harmlessly return, doing so without eliminating the confusion regarding the ownership of IDisposable will not result in more serious problems will not be resolved.

Key scenarios in which repeated deletion attempts should not be considered as indicating wider problems,

  1. Situations in which the creation of an object is not performed with a partially constructed object; while it would be possible to define a policy regarding which parts of a partially constructed object are responsible for cleaning other parts, it may be easier to just have each part that had to do an “emergency” cleaning to tell every part that it knows about do the same if it has not already been. In most scenarios, removing confusion about the ownership of objects can cause the objects to be used during use, but if the factory object does not work, this usually means that references to the object were not issued to anyone who would use them.
  2. Situations in which deleting the object that is being used is a legitimate usage scenario with predictable semantics. For example, some data sources block wait methods and explicitly indicate that deleting a data source while waiting for a block method will cause this method to end without additional delay. In some cases, it is entirely possible that pulling a one-time resource out from under a task that uses it is the only way to debug such a task.

    Your script seems a bit like the first, except that it looks like you will get rid of every element after it is added to parent.Items, which would suggest that you might have confusing issues with owning objects.

+2
source

Source: https://habr.com/ru/post/1390480/


All Articles