Which is faster ObservableCollection or IEnumerable to load a listbox?
I am currently using an IEnumerable as the ItemSource of the Listbox.
Will it have any impact on the performance if I change this to ObservableCollection, if it is even possible?
That really depends on which class is implementing the IEnumerable. IEnumerable is simply an interface and any number of classes could be behind the actual implementation. You don't really bind the IEnumerable, since that is an interface, but you are binding some collection/list that implements IEnumerable. ObservableCollection also implements IEnumerable so should be able to safely use that as the ItemSource instead.
Enumerating through a IEnumerable to fill a ListBox should never be a performance bottleneck in your application, unless you would be using some custom class that does a lot of logic when iterating through values, in which case your design would probably be flawed.
That being said, the best way is of course to simply measure. There is no substitute for measuring and making assumptions is always likely to come back to bite you later.
I'm quite new to WPF and C#, but what I have understood so far is that if you use an IEnumerable as ItemSource, such as a List, you won't be able to see changes in that List unless you replace it with a different one:
IEnumerable<int> myList = new List<int>();
myList.Add(3);
In this case (provided that you do all the necessary stuff to inform your GUI that myList is changed) nothing will happen. If you do something like this, instead:
myList = new List<int> { 100, 200, 300 };
your GUI will be informed.
If you use a ObservableCollection, instead, your GUI will be informed even when you add a new element with the Add method. So you have to decide whether you want to add elements to your ListBox or not.
If you bind to a collection that implements IEnumerable and that is not an ObservableCollection, for example a List, the binding target will not be notified of items added/removed.
Not using a ObservableCollection does only make sense if the number of items in the collection does not change. Only then it makes sense to compare ObservableCollection with other objects. If the number of items change, then you do not have any choice but using an ObservableCollection.
In addition, as already pointed out by other users, you do not have to compare ObservableCollection with IEnumerable, but with a class implementing IEnumerable.
As an example, a comparison ObservableCollection - List can be found in Stack Overflow question ObservableCollection<> vs. List<>.
Related
In the process of adhering to code analysis errors, I'm changing my properties to have private setters. Then I started trying to understand why a bit more. From some research, MS says this:
A writable collection property allows a user to replace the collection with a completely different collection.
And the answer, here, states:
Adding a public setter on a List<T> object is dangerous.
But the reason why it's dangerous is not listed. And that's the part where I'm curious.
If we have this collection:
public List<Foo> Foos { get; set; }
Why make the setter private? Apparently we don't want client code to replace the collection, but if a client can remove every element, and then add whatever they want, what's the point? Is that not the same as replacing the collection entirely? How is value provided by following this code analysis rule?
Not exposing the setter prevents a situation where the collection is assigned a value of null. There's a difference between null and a collection without any values. Consider:
for (var value in this.myCollection){ // do something
When there are no values (i.e. someone has called Remove on every value), nothing bad happens. When this.myCollection is null, however, a NullReferenceException will be thrown.
Code Analysis is making the assumption that your code doesn't check that myCollection is null before operating on it.
It's probably also an additional safeguard for the thread-safe collection types defined in System.Collections.Concurrent. Imagine some thread trying to replace the entire collection by overwritting it. By getting rid of the public setter, the only option the thread has is to call the thread-safe Add and Remove methods.
If you're exposing an IList (which would be better practice) the consumer could replace the collection with an entirely different class that implements IList, which could have unpredictable effects. You could have subscribed to events on that collection, or on items in that collection that you're now incorrectly responding to.
In addition to SimpleCoder's null checking (which is, of course, important), there's other things you need to consider.
Someone could replace the List, causing big problems in thread safety
Events to a replaced List won't be sent to subscribers of the old one
You're exposing much, much more behavior then you need to. For example, I wouldn't even make the getter public.
To clarify point 3, don't do cust.Orders.clear(), but make a function called clearOrders() instead.
What if a customer isn't allowed to go over a credit limit? You have no control over that if you expose the list. You'd have to check that (and every other piece of business logic) every place where you might add an order. Yikes! That's a lot of potential for bugs. Instead, you can place it all in an addOrder(Order o) function and be right as rain.
For almost every (I'd say every, but sometimes cheating feels good...) business class, every property should be private for get and set, and if feasible make them readonly too. In this way, users of your class get only behaviors. Protect as much of your data as you can!
ReadOnlyCollection and ReadOnlyObservableCollection exists only for read only collection scenearios.
ReadOnlyObservableCollection is very useful for one way binding in WPF/Silverlight/Metro apps.
If you have a Customer class with a List Property then this property should always have a private setter else it can be changed from outside the customer object via:
customer.Orders = new List<Order>
//this could overwrite data.
Always use the add and remove methods of the collection.
The Orders List should be created inside the Customer constructor via:
Orders = new List<Order>();
Do you really want to check everywhere in your code wether the customer.Orders != null then operate on the Orders?
Or you create the Orders property in your customer object as suggested and never check for customer.Orders == null instead just enumerate the Orders, if its count is zero nothing happens...
Sometimes it is useful to enumerate a list while it is changing.
e.g.
foreach (var item in listOfEntities)
item.Update();
// somewhere else (with someEntity contained in listOfEntities)
// an add or remove is made:
someEntity.OnUpdate += (s,e) => listOfEntities.Remove(someEntity);
This will fail if listOfEntities is a List<T>.
There are workarounds like making a copy or a simple for-loop, each with different drawbacks, but I would like to know if there is a list type in the framework (or open source) that supports this.
Look at the collections in System.Collections.Concurrent. There's no list there, but the collections' enumerators do "represents a moment-in-time snapshot of the contents of the [collection]".
These collections are designed for access from multiple threads, so they will be better suited to applications like the code sample you posted.
This has nothing to do with List<T>; it is a limitation of the enumerator. If you change the state of the collection underneath the enumerator it will throw, period.
You could use a for loop, but you will then run into logical errors as you index into a collection after the number of items have changed.
It's probably a bad idea to swap items in and out of a collection while you are enumerating it in another thread. I would stick with the tried and true method of recording the items to be removed in another collection or locking the collection while it is being enumerated.
I'm not claiming this is an impossible problem to solve, I just don't know of an easy way to do it.
Basically, I was always in the understanding that you should return the expose base types whenever you can and worry about implementation details internally, which makes sense...
But, I'm not sure what to do here. Basically, right now I have:
ReadOnlyObservableCollection<Foo> MyFoos {get; private set; }
I'm wondering if that should be returned as a ReadOnlyCollection<Foo> or an ICollection<Foo> because internally I never really use any observable parts or attempt to write to the collection. WPF seems to not care what I return, it still binds it and triggers the collection changed notification event properly. But, I read somewhere that I should design this to really have any consuming view handle my ViewModel.
So I'm a bit torn here. I'm thinking that leaving it as a ReadOnlyObservableCollection<T> makes the most sense to explicitly tell the consuming view what they can and can not do with the property, but I'm also under the impression that you should reduce down types to their base types when you can. So I'm not sure what to do here. Especially with the fact that WPF doesn't care what type I return, it figures out that it's observable.
I would probably leave it as ReadOnlyObservableCollection because that very specifically states what a consumer of your ViewModel is allowed to do with your collection. Also note that WPF doesn't actually bind directly to your collection, it binds to the return value of CollectionViewSource.GetDefaultView, which returns an ICollectionView. ICollectionView has INotifyCollectionChanged in its contract.
From a performance perspective, you would want to at least use an items source as a collection that implements INotifyCollectionChanged. MVVM provides a lot of benefits but is primarly concerned with unit testing and separation of concerns, so that choice of whether to use a ReadOnlyObservableCollection or an interface like ICollection{T} would be based on your unit testing goals.
I'm interested the most efficient way to change an observable collection in such a way that only one property changed is fired. Lets say that I want to populate the list with 3 items, there is no addCollection method or something like that, so I have to do clear + 3 times add. Do I need to create a different observable collection and assign? Or what techniqies do others use?
NET Framework's ObservableCollection class sends individual notifications on as each item added to the collection and provides no mechanism for AddRange-type functionality. However you can very easily create your own collection that implements INotifyCollectionChanged and send whatever notifications you like.
On issue you may encounter is that the INotifyCollectionChanged interface includes the ability to specify that multiple items were added to the collection in a single message, but no standard NET Framework classes actually create these notifications. Because of this, some third-party and open source controls that assume only one item has been added when they receive an Add notification. Even the built-in NET Framework classes may have undiscovered bugs related to this.
For these reasons I would recommend your custom collection have a mode in which it can be set to always send a Reset notification at the end of an AddRange instead of a single multi-item Add notification. You could optimize this further by sending multiple single-item Add notifictions or a Reset notification depending on the actual number of items added.
Of course there are situations in which it is just as easy to replace the ObservableCollection with a new one. At times this will be much less efficient than looping Add() because event handlers and CollectionViews are rebuilt. Other times it will be more efficient if the collection is large and your loop only adds a few items at a time.
And sometimes it won't work at all.
I have an object in a multi-threaded environment that maintains a collection of information, e.g.:
public IList<string> Data
{
get
{
return data;
}
}
I currently have return data; wrapped by a ReaderWriterLockSlim to protect the collection from sharing violations. However, to be doubly sure, I'd like to return the collection as read-only, so that the calling code is unable to make changes to the collection, only view what's already there. Is this at all possible?
If your underlying data is stored as list you can use List(T).AsReadOnly method.
If your data can be enumerated, you can use Enumerable.ToList method to cast your collection to List and call AsReadOnly on it.
I voted for your accepted answer and agree with it--however might I give you something to consider?
Don't return a collection directly. Make an accurately named business logic class that reflects the purpose of the collection.
The main advantage of this comes in the fact that you can't add code to collections so whenever you have a native "collection" in your object model, you ALWAYS have non-OO support code spread throughout your project to access it.
For instance, if your collection was invoices, you'd probably have 3 or 4 places in your code where you iterated over unpaid invoices. You could have a getUnpaidInvoices method. However, the real power comes in when you start to think of methods like "payUnpaidInvoices(payer, account);".
When you pass around collections instead of writing an object model, entire classes of refactorings will never occur to you.
Note also that this makes your problem particularly nice. If you don't want people changing the collections, your container need contain no mutators. If you decide later that in just one case you actually HAVE to modify it, you can create a safe mechanism to do so.
How do you solve that problem when you are passing around a native collection?
Also, native collections can't be enhanced with extra data. You'll recognize this next time you find that you pass in (Collection, Extra) to more than one or two methods. It indicates that "Extra" belongs with the object containing your collection.
If your only intent is to get calling code to not make a mistake, and modify the collection when it should only be reading all that is necessary is to return an interface which doesn't support Add, Remove, etc.. Why not return IEnumerable<string>? Calling code would have to cast, which they are unlikely to do without knowing the internals of the property they are accessing.
If however your intent is to prevent the calling code from observing updates from other threads you'll have to fall back to solutions already mentioned, to perform a deep or shallow copy depending on your need.
I think you're confusing concepts here.
The ReadOnlyCollection provides a read-only wrapper for an existing collection, allowing you (Class A) to pass out a reference to the collection safe in the knowledge that the caller (Class B) cannot modify the collection (i.e. cannot add or remove any elements from the collection.)
There are absolutely no thread-safety guarantees.
If you (Class A) continue to modify the underlying collection after you hand it out as a ReadOnlyCollection then class B will see these changes, have any iterators invalidated, etc. and generally be open to any of the usual concurrency issues with collections.
Additionally, if the elements within the collection are mutable, both you (Class A) and the caller (Class B) will be able to change any mutable state of the objects within the collection.
Your implementation depends on your needs:
- If you don't care about the caller (Class B) from seeing any further changes to the collection then you can just clone the collection, hand it out, and stop caring.
- If you definitely need the caller (Class B) to see changes that are made to the collection, and you want this to be thread-safe, then you have more of a problem on your hands. One possibility is to implement your own thread-safe variant of the ReadOnlyCollection to allow locked access, though this will be non-trivial and non-performant if you want to support IEnumerable, and it still won't protect you against mutable elements in the collection.
One should note that aku's answer will only protect the list as being read only. Elements in the list are still very writable. I don't know if there is any way of protecting non-atomic elements without cloning them before placing them in the read only list.
You can use a copy of the collection instead.
public IList<string> Data {
get {
return new List<T>(data);
}}
That way it doesn't matter if it gets updated.
You want to use the yield keyword. You loop through the IEnumerable list and return the results with yeild. This allows the consumer to use the for each without modifying the collection.
It would look something like this:
List<string> _Data;
public IEnumerable<string> Data
{
get
{
foreach(string item in _Data)
{
return yield item;
}
}
}