I am currently implementing the INotifyCollectionChanged interface for a collection with generally quite critical and short-lived items. All of those items implement IDispose, which can be called immediatly before the removal from the collection. I do not have any control about the destruction order, I will just have to take it as it comes.
My trouble is now, how to propagate the "Remove" actions. The NotifyCollectionChangedAction constructor does provide a variant with only the action specified, but I do have an index of the removed item. Sadly there is no overload taking only an index.
So I guess I could:
Only pass the "Remove" action
Pass the remove action along with a "null" object and an index
Pass the remove action along with a disposed object and an index
Which of those would you prefer? I am a little afraid of implementing such a "core" interface wrong and possibly cause not obviously related bugs ...
I couldn't find any guidelines what happens with the items that are in the "change" lists, are there any available?
Sidenote: The collection will not be immediatly bound to WPF, if thats important.
From what I can see in MSDN, the only appropriate sets of data for remove are the overload taking the instance, and the overload taking instance and index. You could try the latter passing just the index; it might work... but given the existence of the first overload, I'm not hopeful. If you don't give it the object, downstream code may have no way of knowing which item changed. So I think you're going to have to pass the object. This shouldn't generally cause issues, as most code is simply going to use it for reference check; the object is still there (it hasn't been collected) - it has just been disposed, where "just" is used... subjectively (as this could still cause issues).
Another option, of course, is to wrap the object in a facade. Then it doesn't matter if the actual object is disposed, set to null and/or garbage-collected; the facade is still there (but it should be coded to handle the object being unavailable).
As a final option; do you have to use their collection? Could you not just wrap that collection, so that you choose when to tell it about these things? THen you retain complete control over lifetimes...
Basically you are borked.
Destruction of objects before the removal is a violation of how the interface should work. Point. You can not control it - then you can not implemtn NotifyCollectionChangedAction properly.
You have to pass the index and the removed object.
Related
If i have public method that returns a reference type value, which is private field in the current class, do i need to return a copy of it? In my case i need to return List, but this method is called very often and my list holds ~100 items. The point is that if i return the same variable, everybody can modify it, but if i return a copy, the performance will degrade. In my case im trying to generate sudoku table, which is not fast procedure.
Internal class SudokuTable holds the values with their possible values. Public class SudokuGame handles UI requests and generates/solves SudokuTable. Is it good practice to chose performance instead OOP principles? If someone wants to make another library using my SudokuTable class, he wont be aware that he can brake its state with modifying the List that it returns.
Performance and object-oriented programming are not mutually exclusive - your code can be object-oriented and perform badly, etc.
In the case you state here I don't think it would be wise to allow external parts edit the internal state of a thing, so I would return an array or ReadOnlyCollection of the entries (it could be a potential possibility to use an ObservableCollection and monitor for tampering out-of-bounds, and 'handling' that accordingly (say, with an exception or something) - unsure how desirable this would be).
From there, you might consider how you expose access to these entries, trying to minimise the need for callers to get the full collection when all they need is to look up and return a specific one.
It's worth noting that an uneditable collection doesn't necessarily mean the state cannot be altered, either; if the entries are represented by a reference type rather than a value type then returning an entry leaves that open to tampering (potentially, depending on the class definition), so you might be better off with structs for the entry types.
At length, this, without a concrete example of where you're having problems, is a bit subjective and theoretical at the moment. Have you tried restricting the collection? And if so, how was the performance? Where were the issues? And so on.
(Using VS2010. Assume performance is not an issue).
I have a particular object that implements events for all its property changes. Sometimes it will be necessary to "reset" the object to all its default property values. The easiest way to do this is simply construct a new object:
Object1= New MyObject
However, for any event subscribers to the original object, this is equivalent to a change of all property values. For example, if a subscriber was listening only for updates to property A, now it must also be aware of the possibility of new object construction. This seems to add extra effort for subscribers. (For example, maybe I would have to create a "NewObjectAssigned" event, and subscribers to property changes would need to handle that as well.)
So instead I was thinking of outfitting the object with a Reset method, so the above code changes to:
Object1.Reset
That way the Object1 reference never changes, and the Reset would manually change all properties to default values, thereby triggering all propertychanged events. But this also doesn't feel quite right, and cumbersome compared to just declaring a new object. I guess it irks me to need a method that either manually resets all properties or raises all changed events - I'd have to remember to update this method whenever new properties are added to the class. Or perhaps this isn't as problematic as I'm making it out to be.
This is a simple enough scenario that I'm sure there is a best practices for this, one way or another. Which is preferable?
If you need your event handlers to stay attached, then you'll want to use a reset instead of creating a new instance. If your object implements INotifyPropertyChanged, then you can send a single event for the reset with PropertyName set to null.
From MSDN:
An Empty value or null for the propertyName parameter indicates that all of the properties have changed.
I think I agree with Peter Ritchie's first comment, that my original question was lacking in details necessary to determine a "preferable" method. As it stands, I'm probably going with his suggestion of a wrapper class, that will be responsible for handling new object references and exposing events to subscribers.
I'm trying to nut out the details for a true WeakKeyedDictionary<,> for C#... but I'm running into difficulties.
I realise this is a non-trivial task, but the seeming inability to declare a WeakKeyedKeyValuePair<,> (where the GC only follows the value reference if the key is reachable) makes it seemingly impossible.
There are two main problems I see:
Every implementation I've so far seen does not trim values after keys have been collected. Think about that - one of the main reasons for using such a Dictionary is to prevent those values being kept around (not just the keys!) as they're unreachable, but here they are left pointed to by strong references.
Yes, add/remove from the Dictionary enough and they'll eventually be replaced, but what if you don't?
Without a hypothetical WeakKeyedKeyValuePair<,> (or another means of telling the GC to only mark the value if the key is reachable) any value that refers to it's key would never be collected. This is a problem when storing arbitrary values.
Problem 1 could be tackled in a fairly non-ideal/hackish way : use GC Notifications to wait for a full GC to complete, and then go along and prune the dictionary in another thread. This one I'm semi-ok with.
But problem 2 has me stumped. I realise this is easily countered by a "so don't do that", but it has me wondering - is this problem even possible to solve?
Have a look at the ConditionalWeakTable<TKey, TValue> Class.
Enables compilers to dynamically attach object fields to managed objects.
It's essentially a dictionary where both the key and the value are a WeakReference, and the value is kept alive as long as the key is alive.
Note! This class does not use GetHashCode and Equals to do equality comparisons, it uses ReferenceEquals.
I am writing a facade for IList<T> to implement change tracking. Does Clear use RemoveAt or Remove or something else entirely? I need to know if I need to set all the items tracking state inside of Clear or if changing the tracking state only in Remove, and RemoveAt will be enough.
Similarly, does Add use Insert? Does Remove or RemoveAt use each other?
Any other input into such an implementation is also welcome.
Edit: Do extension methods for List use pre-existing methods or is it new code? I don't know if I need to implement those as well.
Does Clear use RemoveAt or Remove or something else entirely?
You can not rely on implementations of IList.Clear to use IList.RemoveAt or IList.Remove. It is up to the specific implementation to do whatever it wants.
Note that you can't even really rely on Clear actually removing all items from the instance. An interface does not enforce behavior, it is not actually a contract.
There's a huge misconception on what interfaces actually are. You'll hear people say that "interfaces are contracts". They are not. They merely specify that there will be some methods with certain signatures and return types that you will be able to invoke if you have an object that implements a given interface. That's it. There is no guarantee whatsoever on the implementation, or the behavior.
Additionally, relying on implementation details is a gigantic code smell. They could change on you at any moment without you knowing causing your code to fail and die miserably. Do not rely on implementation details.
Similarly, does Add use Insert?
Similarly, you can not rely on IList.Add using IList.Insert.
Does Remove or RemoveAt use each other?
You can not rely on it being true.
It doesn't matter if you write a facade since these methods are not virtual. Event if implementation of Clear called Remove (it doesn't) it wouldn't be your overriden Remove.
So that makes your life easier. You are free to implement this tracking fully in your wrapper.
IList is simply a contract. What a class implementing IList does behind the scenes is its own business and it doesn't have to make any promises. Some implementors might iterate through their items and call Remove against them, while others might just delete their backing store and create a new one, or many other possibilities.
It's probably not a good idea to assume someone implementing an interface implements it in a certain way. This is certain to break in unexpected ways at some point.
From source, List<T> uses Array.Clear()
// Clears the contents of List.
public void Clear() {
if (_size > 0)
{
Array.Clear(_items, 0, _size); // Don't need to doc this but we clear the elements so that the gc can reclaim the references.
_size = 0;
}
_version++;
}
I'm implementing my own BindingList<T> that supports sorting. Everything is working well so far, but I'm confused about how I should implement RemoveSortCore. The documentation is not very explicit, it only says:
Removes any sort applied with ApplySortCore if sorting is implemented in a derived class
Does that mean I should restore the original order of the items? The implementation shown in this MSDN article only sets _isSorted to false, without actually restoring the original order, which makes it quite useless IMHO...
If I want to be able to restore the original order, I guess I need to maintain a copy of the original collection (or is there a better way?). But if I do that, how do I handle modifications of the collection while it is sorted?
When overriding InsertItem, should I just add the new item at the end of the unsorted copy?
When overriding RemoveItem, I'm given the index in the sorted collection. But it means that if I want to also remove the item from the unsorted collection, I need to find its original position, which is an O(n) operation, while RemoveItem is normally expected to be an O(1) operation. The same question also applies to SetItem.
How would you handle that? Any suggestions are welcome
It is up to the implementer to define exactly what this means. The two most obvious choices are:
Revert the list to the original form: Official example here
Remove the Sort and proceed as if one had never been applied: As used in MS.SqlServer.Management.Controls.SortableBindingList