Dictionary or KeyedCollection? - c#

I have a class (SomeClass) which contains a property Name of string type. And I need to store an array of that class and find its items by their names. For this purpose there are two types of collections: KeyedCollection and Dictionary. My question is: What difference between them and in such case It is better to use KeyedCollection and Dictionary? Thanks for any help in explanation.

None of the previous comments address the most important difference between the two:
KeyedCollection keeps your items in the order in which they are added (the first item added is at index 0 and the last added is at the last index). Dictionary does not (or at least it is never guaranteed to do so).
This extra benefit of KeyedCollection does have a small performance cost. Under the covers, you pay the cost of maintaining both a Dictionary and a List.

Here is good explanation about differences between Dictionary and KeyedCollection: http://geekswithblogs.net/NewThingsILearned/archive/2010/01/07/using-keyedcollectionlttkey-titemgt.aspx
Main points are:
KeyedCollection is abstract, so you can't use it directly.
KeyedCollection is useful for cases, when key is in entity itself, then you can encapsulate key retrieval within collection implementation.
There are generic implementations for KeyedCollection (not in the framework though), which allow you to paste key retrieval delegate in collection constructor, so you don't have to repeat it each time you add item.
Update: as long as original link to article was removed, adding link to web archive: https://web.archive.org/web/20200228045828/http://geekswithblogs.net/NewThingsILearned/archive/2010/01/07/using-keyedcollectionlttkey-titemgt.aspx

A KeyedCollection allows mutable keys and ways to manage change in key. Dictionary does not allow changes to key. Secondly, if you have a collection which needs lookup, the logic to extract key from entity remains in one place - whereas maintaining dictionary will need to put key extraction logic at each place where items are added/removed from dictionary.

By default a KeyedCollection creates a Dictionary under the covers.
If the Key also has meaning as part of the Value and also defines uniqueness then that is the purpose of a KeyedCollection.
If you want to modify the dictionary backing then use this ctor:
protected KeyedCollection(
IEqualityComparer<TKey> comparer,
int dictionaryCreationThreshold)

A KeyedCollection should be used when the key is on the item itself.
By default, KeyedCollection is a Collection<TItem> wrapper around a dictionary. When you use small collections and/or you prefer retrieving items directly, the KeyedCollection provides a constructor that takes a dictionaryCreationThreshold parameter, that indicates at what collection count to switch to Dictionary.
Another aspect in KeyedCollection is that you can choose to switch the key property (as long as their types match). This can be good for double keyed items etc.
Performancewise, I don't think wrapping a dictionary has much overhead except if you generate a bunch of KeyedCollection instances, or if you use really large collections (there are some internal null checks to determine if there is a dictionary).
One thing I'd hope to see in KeyedCollection is unabstracting it, but you can make a generic concrete type just as easy.

You can't use KeyedCollection because it's abstract: http://msdn.microsoft.com/en-us/library/ms132438.aspx. This means you can't create an object of it.

Related

Is it possible to access Expandoobject properties by index?

It is possible to override the TryGetIndex method of a dynamic object to access the dynamic object properties by index however I am dealing with an Expandoobject (of the System.dynamic namespace) which you can't inherit from. Is there a way around this? Thanks
ExpandoObject is nothing but a fancy IDictionary which leverages the DLR.
There is no way you can access a IDictionary<TKey,TValue> via index. You may find ElementAt method of linq useful, but it is not. There is no ordering in dictionary, You can read more about hashtable datastructure(Dictionary is also a hashtable).
For accessing dictionary via index you may use OrderedDictionary. One disadvantage is that is is not generic.
Know more about issues when accessing elements via index from a Dictionary

Data type for storing object pair other than Dictionary in C#

What would be the best data type for storing non-unique pairs of objects? I cannot use Dictionary because the key has to be unique. I could create an object with the two data types as properties and store them in a list, but that wouldn't be flexible enough to accommodate the different data type pairs. Something almost like Dictionary but non-unique. A build-in solution from .NET would be even better.
I think a List<Tuple<T1,T2>> would work best here.
List<T>
Tuple<T1,T2>
You could use List<KeyValuePair<T1,T2>>. Dictionary class uses KeyValuePair too.

Which data structure/class I can use to represent one-to-many relation?

I am trying to write a program that would use a data structure/class that will hold multiple data entries for one key - this will be somehow similar to Dictionary but it's not one to one but one to many relation. I am trying to think of a class that I can use but I cannot figure anything out.
For instance how it may look like:
I have a parameter xValue and 3 different values in different files so i would have :
xValue, <1.txt, 1>
xValue, <2.txt, 2>
xValue, <3.txt, 3>
Any ideas ?
EDIT:
I have figured this out - After all I can use
Dictionary< string , Dictionary<..., ... > >
, can't I ?
As there is no multiset in .NET natively, I would go for
Dictionary<Key, HashSet<XValue>>
in your case.
If you are ok with using 3rd-party containers, you can look up the answers from here, e.g., Wintellect PowerCollections.
If you do not need modify this collection after initialization and just need to do search, you can leverage built in Lookup<TKey, TElement> class, but really this would be tricky and useful in rare cases when you already have IEnumerable<> instances and would flatten it to lookup data structure, anyway this is pretty useful to keep in mind that .NET provides such intersting class.
MSDN
Represents a collection of keys each mapped to one or more values. A
Lookup<TKey, TElement> resembles a Dictionary<TKey, TValue>. The
difference is that a Dictionary<TKey, TValue> maps keys to single
values, whereas a Lookup<TKey, TElement> maps keys to collections of
values.
You can not instantiate it explicitly and just can get instance of lookup using LINQ ToLookup() method. There are major restrictions so you can use this class as lookup data structure - doing search.
There is no public constructor to create a new instance of a
Lookup. Additionally, Lookup objects
are immutable, that is, you cannot add or remove elements or keys from
a Lookup object after it has been created.

Using Custom Generic Collection faster with objects than List

I'm iterating through a List<> to find a matching element. The problem is that object has only 2 significant values, Name and Link (both strings), but has some other values which I don't want to compare.
I'm thinking about using something like HashSet (which is exactly what I'm searching for -- fast) from .NET 3.5 but target framework has to be 2.0. There is something called Power Collections here: http://powercollections.codeplex.com/, should I use that?
But maybe there is other way? If not, can you suggest me a suitable custom collection?
In .NET 2.0 instead of a HashSet<T> you can use a Dictionary<K, V>.
Dictionary uses the hash code to perform key lookups so it has similar performace to the HashSet. There are at least two approaches:
Create a custom class or struct containing the Name and Link and use that as the key in the dictionary, and put the object as the value.
Store the entire object as the key and provide a custom equality comparer that only looks at the Name and Link member, and set the value to null.
The second method is very similar to how you would use a HashSet if it were available.
How about this:
Custom class/collection wich will held List of objects and two dictionaries, one for the name and one for the link. Both of them will have a int value wich will be the index of object. I think that in that case I will only need to check if there is such int value of name dictionary that equals link dictionary int.
Is this a good approach?

Is this way of using Dictionary<enum,object> correct in this Production Planning example?

Consider a production planning application with many products. Each product has a list of InventoryControl objects keyed on InventoryControlType. Depending on the algorithm we run for production planning, we need to access to different types of InventoryControl objects for a given product. This works OK. However, today I needed to introduce a field in InventoryControl that holds the InventoryControlType since deep in our algorithms we needed to know the InventoryControlType.
However, I felt felt like I was doing something wrong since it looks like I am repeating data.
Does this design look OK to you? Any ideas for improvement?
class Product{
Dictionary<InventoryControlType, InventoryControl> InventoryControls;
GetInventoryControl(InventoryControlType type){
return InventoryControls[type];
}
}
class InventoryControl{
InventoryControlType controlType;
float limit;
float cost;
...
CalculateCost(){...}
GetConstraint(){...}
}
I think you're fine. It's perfectly normal (at least in my experience) to use a unique property of an object as a key--be it in a Dictionary, a DataTable, or what have you.
For example in my own work our major project features a class called Product with a property called Symbol, and the application maintains a Dictionary called Products with each Product object's Symbol property serving as its key.
Think of it this way: if you have a database with two tables, and one table references rows in the other by key, it may feel like you are "duplicating" data in the sense that you have the same number (the key) in two places. But that is not duplication; it's a reference. The same applies in your scenario.
I don't see anything inherently wrong with it. It is duplicating a piece of information, but the situation does call for it. You could use a normal collection instead of a Dictionary--but because your main goal is to find a piece of information based on its InventoryControlType, Dictionary, with this implementation, seems most correct.
I think it's absolutely fine for a Dictionary<TKey, TValue> use case.
Many times Dictionary objects will always have some sort of redundant information from the value object, the most common of which will be an ID, e.g. Dictionary<int, SomeObject> where int will be a value taken from SomeObject.Id -- it makes sense in that respect, and it's perfectly identical to your use case.
It really depends on how big the dictionary is supposed to get, because for very large amounts of data, I think the lookup on the dictionary using the key would probably be faster. But if you don't have very large amounts of data, you could use Linq and a Generic List. For example:
class Product{
List<InventoryControl> InventoryControls;
GetInventoryControl(InventoryControlType type){
return InventoryControls.First(x => x.ControlType == type);
}
I would recommend running some unit test benchmarks to see whether the Dictionary is required.

Categories