I'm completely new to C#, so I'm about to make a horrible attempt at my own version of an OrderedDictionary unless someone can suggest an alternative.
I need to be able to access my elements by array index, retaining the order they were added, and I also will be frequently updating individual elements using their key.
Is there a collection that allows this on the phone?
If I keep a List and Dictionary will they both be pointing to the same item or is there some kind of pointer thing I have to do?:
Item i = new Item();
list.Add(i);
dict.Add("key", i);
Here's my implementation (comes from the open source OpenNETCF Extensions library):
public class OrderedDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
{
private Dictionary<TKey, TValue> m_dictionary;
private List<TValue> m_list = new List<TValue>();
private object m_syncRoot = new object();
public OrderedDictionary()
{
m_dictionary = new Dictionary<TKey, TValue>();
}
public OrderedDictionary(IEqualityComparer<TKey> comparer)
{
m_dictionary = new Dictionary<TKey, TValue>(comparer);
}
public void Add(TKey key, TValue value)
{
lock (m_syncRoot)
{
m_dictionary.Add(key, value);
m_list.Add(value);
}
}
public TValue this[int index]
{
get { return m_list[index]; }
}
public TValue this[TKey key]
{
get { return m_dictionary[key]; }
}
public int Count
{
get { return m_dictionary.Count; }
}
public Dictionary<TKey, TValue>.KeyCollection Keys
{
get { return m_dictionary.Keys; }
}
public Dictionary<TKey, TValue>.ValueCollection Values
{
get { return m_dictionary.Values; }
}
public void Clear()
{
lock (m_syncRoot)
{
m_dictionary.Clear();
m_list.Clear();
}
}
public bool ContainsKey(TKey key)
{
return m_dictionary.ContainsKey(key);
}
public bool ContainsValue(TValue value)
{
return m_dictionary.ContainsValue(value);
}
public void Insert(int index, TKey key, TValue value)
{
lock (m_syncRoot)
{
m_list.Insert(index, value);
m_dictionary.Add(key, value);
}
}
public void Remove(TKey key)
{
lock (m_syncRoot)
{
if (ContainsKey(key))
{
var existing = m_dictionary[key];
m_list.Remove(existing);
m_dictionary.Remove(key);
}
}
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return m_dictionary.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Using a List and a Dictionary is probably a good option actually. The "pointer thing" that you're talking about happens by default for Objects in .NET (any class and/or structure). All objects in .NET are passed around by reference.
So, if you use:
Item i = new Item();
list.Add(i);
dict.Add("key",i);
Console.WriteLine(list.Last() == dict["key"]);
Your output will be "true".
Best of luck!
I won't suggest using OrderedDictionary, since it's a non-generic container.
However, if you just want to use it like always. You can port Mono's version of OrderedDictionary.
https://github.com/mono/mono/blob/master/mcs/class/System/System.Collections.Specialized/OrderedDictionary.cs
Here's some tips if you want to port this:
Remove any unavailable interface
Remove serialization-related code
Replace ArrayList with List<object>
Replace Hashtable with Dictionary<object, object>
Related
I have a Dictionary with a custom hashing function. I want to test the hash function, because even though it returns different hash results for my test values, some of them may still map to the same bucket due to the modulo % operation. So how to check if there are collisions in C# Dictionary with custom hash function and improve that function?
This is a development test to fine-tune the hash function and won't go into production so no worries about the changes in internal implementation in other versions!!!
In C++ it's possible to get the map's bucket size to check the collision status but I couldn't find a way to do that in C#. How can I know if Dictionary has been collided?
You can get internal buckets in the following way:
var dictionary = new Dictionary<string, int>();
dictionary.Add("a", 8);
dictionary.Add("b", 1);
var buckets = dictionary.GetType().GetField("_buckets", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(dictionary); // use "buckets" for 4.x
You're probably better off creating a custom Dictionary implementation that changes the Add and Remove methods to check for hash collisions based on the computer GetHashCode of the elements. You can compose with a "real" Dictionary internally to do the real work of storing the elements.
Here's a sample version. You could optimize the Add and Remove methods depending on the type of hashes your expecting.
public class CollisionDetectingDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
private readonly Dictionary<TKey, TValue> InternalDictionary = new Dictionary<TKey, TValue>();
private readonly List<int> HashCodesInDictionary = new List<int>();
public event Action<int, TKey, IEnumerable<TKey>> HashCollision;
public TValue this[TKey key] { get => InternalDictionary[key]; set => InternalDictionary[key] = value; }
public ICollection<TKey> Keys => InternalDictionary.Keys;
public ICollection<TValue> Values => InternalDictionary.Values;
public int Count => InternalDictionary.Count;
public bool IsReadOnly => false;
public void Add(TKey key, TValue value)
{
Add(new KeyValuePair<TKey, TValue>(key, value));
}
public void Add(KeyValuePair<TKey, TValue> item)
{
var hashCode = item.Key.GetHashCode();
if (HashCodesInDictionary.Contains(hashCode))
{
var collisions = GetKeysByHashCode(hashCode);
HashCollision?.Invoke(hashCode, item.Key, collisions);
}
Add(item);
}
private IEnumerable<TKey> GetKeysByHashCode(int hashCode)
{
foreach (var key in Keys)
{
if(key.GetHashCode() == hashCode)
{
yield return key;
}
}
}
public void Clear()
{
InternalDictionary.Clear();
}
public bool Contains(KeyValuePair<TKey, TValue> item)
{
return InternalDictionary.Contains(item);
}
public bool ContainsKey(TKey key)
{
return InternalDictionary.ContainsKey(key);
}
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
((IDictionary<TKey,TValue>)InternalDictionary).CopyTo(array, arrayIndex);
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return InternalDictionary.GetEnumerator();
}
public bool Remove(TKey key)
{
var hashCode = key.GetHashCode();
if(GetKeysByHashCode(hashCode).Count() == 1)
{
HashCodesInDictionary.Remove(hashCode);
}
return InternalDictionary.Remove(key);
}
public bool Remove(KeyValuePair<TKey, TValue> item)
{
return Remove(item.Key);
}
public bool TryGetValue(TKey key, out TValue value)
{
return InternalDictionary.TryGetValue(key, out value);
}
IEnumerator IEnumerable.GetEnumerator()
{
return InternalDictionary.GetEnumerator();
}
}
I require a thread safe collection but are unable to use ConcurrentDictionary as its .NET 4.0, and I need to use .NET 3.5. What are alternatives are out there?
In the end I found what I was after. A nuget package of the TPL backported to 3.5. It can be found here
http://nuget.org/packages/TaskParallelLibrary
Have a look at this article
“Thread safe” Dictionary(TKey,TValue)
For Framework 3.5 I see the following options:
Dictionary + Monitor. Simple wrap to lock
Dictionary + ReaderWriterLock. Better than the previous one, because has got read and write locks. So several threads can read, and just one - write.
Dictionary + ReaderWriterLockSlim. It's just optimisation of the previous one.
Hashtable. From my experience, it's the slowest method. Check Hashtable.Synchronized() method, it's a ready to go solution from Microsoft.
I would use Dictionary + ReaderWriterLock or ReaderWriterLockSlim.
You can create a simple wrapper and only implement what you need. Keep in mind that it is not thread safe to perform an operation on a Dictionary that relies on the result of a previous call. This is exemplified in the TryAdd method.
class ConcurrentMap<K, V>
{
readonly Dictionary<K, V> _map = new Dictionary<K, V>();
public bool TryGetValue(K key, out V value)
{
lock (_map)
{
return _map.TryGetValue(key, out value);
}
}
public bool TryAdd(K key, V value)
{
lock (_map)
{
if (!_map.ContainsKey(key))
{
_map.Add(key, value);
return true;
}
return false;
}
}
public bool TryRemove(K key)
{
lock (_map)
{
return _map.Remove(key);
}
}
}
I just needed that for .Net 3.5... someone's still there back :)
adding my class, added some more functionality than previous attached codes.
public class SafeDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
{
private readonly object _Padlock = new object();
private readonly Dictionary<TKey, TValue> _Dictionary = new Dictionary<TKey, TValue>();
public TValue this[TKey key]
{
get
{
lock (_Padlock)
{
return _Dictionary[key];
}
}
set
{
lock (_Padlock)
{
_Dictionary[key] = value;
}
}
}
public bool TryGetValue(TKey key, out TValue value)
{
lock (_Padlock)
return _Dictionary.TryGetValue(key, out value);
}
public bool TryAdd(TKey key, TValue value)
{
lock (_Padlock)
{
if (!_Dictionary.ContainsKey(key))
{
_Dictionary.Add(key, value);
return true;
}
return false;
}
}
public bool TryRemove(TKey key)
{
lock (_Padlock)
{
return _dictionary.Remove(key);
}
}
}
internal void Add(TKey key, TValue val)
{
lock (_Padlock)
{
_Dictionary.Add(key, val);
}
}
public bool ContainsKey(TKey id)
{
lock (_Padlock)
return _Dictionary.ContainsKey(id);
}
public List<KeyValuePair<TKey, TValue>> OrderBy(Func<KeyValuePair<TKey, TValue>, TKey> func)
{
lock (_Padlock)
return _Dictionary.OrderBy(func).ToList();
}
public Dictionary<TKey, TValue>.ValueCollection Values
{
get
{
lock (_Padlock)
return _Dictionary.Values;
}
}
public Dictionary<TKey, TValue>.KeyCollection Keys
{
get
{
lock (_Padlock)
return _Dictionary.Keys;
}
}
IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
{
lock (_Padlock)
return _Dictionary.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
lock (_Padlock)
return _Dictionary.GetEnumerator();
}
}
Each key is unique in the list. When a new key-value pair arrives, the pair is inserted into the list in the ascending order of value (if key already exists then updates the value).
Please avoid sorting the list for every insertion.
I would suggest SortedDictionary or SortedList
As per MSDN :
SortedList uses less memory than SortedDictionary.
SortedDictionary has faster insertion and removal
operations for unsorted data: O(log n) as opposed to O(n) for
SortedList.
Update : After comments
You will have to order the value by yourself for e.g using a dictioanry
var dictionary = new Dictionary<int, string>{ {1, "Z"}, {2, "A"}};
IOrderedEnumerable<KeyValuePair<int, string>> orderedEnumerable = dictionary.OrderBy(d => d.Value);
You aren't going to get a built in component with this behaviour, it's too non-standard. I'd be looking at why and when I needed these competing behaviours. Effectively you are looking at an alternate key. Short of just writing some for of linked list, off the top of my head, I'd look at SortedList for the by value part of it, and a Dictionary for key.
e.g.
a Dictionary of CustomerID and SortKey and a SortedList of SortKey and value.
I'd try and avoid it if I could on the baiss that maintaining both would cost more than simply returning a list of values in the required order on those occasions when you needed it.
If sorting the items for every enumeration is acceptable, you can use a Dictionary<TKey, TValue> and order the key-value pairs by value when you enumerate it:
var dict = new Dictionary<MyKey, MyValue>();
// insertion (updates value when key already exists)
dict[key] = value;
// enumeration (ordered by value)
foreach (var keyValuePair in dict.OrderBy(kvp => kvp.Value))
{
...
}
I would write an ad-hoc class like the following (not completely tested):
public class DictionarySortedByValue<TKey, TValue> : IDictionary<TKey, TValue>
{
class ValueWrapper : IComparable, IComparable<ValueWrapper>
{
public TKey Key { get; private set; }
public TValue Value { get; private set; }
public ValueWrapper(TKey k, TValue v)
{
this.Key = k;
this.Value = v;
}
public int CompareTo(object obj)
{
if (!(obj is ValueWrapper))
throw new ArgumentException("obj is not a ValueWrapper type object");
return this.CompareTo(obj as ValueWrapper);
}
public int CompareTo(ValueWrapper other)
{
int c = Comparer<TValue>.Default.Compare(this.Value, other.Value);
if (c == 0)
c = Comparer<TKey>.Default.Compare(this.Key, other.Key);
return c;
}
}
private SortedSet<ValueWrapper> orderedElements;
private SortedDictionary<TKey, TValue> innerDict;
public DictionarySortedByValue()
{
this.orderedElements = new SortedSet<ValueWrapper>();
this.innerDict = new SortedDictionary<TKey, TValue>();
}
public void Add(TKey key, TValue value)
{
var wrap = new ValueWrapper(key, value);
this.innerDict.Add(key, value);
this.orderedElements.Add(wrap);
}
public bool ContainsKey(TKey key)
{
return this.innerDict.ContainsKey(key);
}
public ICollection<TKey> Keys
{
get { return this.innerDict.Keys; }
}
public bool Remove(TKey key)
{
TValue val;
if (this.TryGetValue(key, out val))
{
var wrap = new ValueWrapper(key, val);
this.orderedElements.Remove(wrap);
this.innerDict.Remove(key);
return true;
}
return false;
}
public bool TryGetValue(TKey key, out TValue value)
{
return this.innerDict.TryGetValue(key, out value);
}
public ICollection<TValue> Values
{
get { return this.innerDict.Values; }
}
public TValue this[TKey key]
{
get
{
return this.innerDict[key];
}
set
{
bool removed = this.Remove(key);
this.Add(key, value);
}
}
public void Add(KeyValuePair<TKey, TValue> item)
{
this.Add(item.Key, item.Value);
}
public void Clear()
{
this.innerDict.Clear();
this.orderedElements.Clear();
}
public bool Contains(KeyValuePair<TKey, TValue> item)
{
var wrap = new ValueWrapper(item.Key,item.Value);
return this.orderedElements.Contains(wrap);
}
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
this.innerDict.CopyTo(array, arrayIndex);
}
public int Count
{
get { return this.innerDict.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
public bool Remove(KeyValuePair<TKey, TValue> item)
{
if (this.Contains(item))
return this.Remove(item.Key);
return false;
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
foreach (var el in this.orderedElements)
yield return new KeyValuePair<TKey, TValue>(el.Key, el.Value);
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
Notes :
it requires that also the TKey type implements IComparable.
the posted code uses only the default Comparer for TKey, and TValue, but
you could pass a custom one through another constructor.
I need some directions here.
I have the following key/value cache:
public class Cache<TKey, TValue> : ICache<TKey, TValue>
{
private readonly IDictionary<TKey, TValue> _internalCache;
private readonly object _syncLock = new object();
public Cache()
{
_internalCache = new Dictionary<TKey, TValue>();
}
public TValue this[TKey key]
{
get
{
lock (_syncLock) {
//...
}
}
set
{
lock (_syncLock) {
//...
}
}
}
public ICollection<TValue> GetAll()
{
lock (_syncLock) {
return _internalCache.Values;
}
}
public bool ContainsKey(TKey key)
{
lock (_syncLock)
{
return _internalCache.ContainsKey(key);
}
}
}
The cache above is used by a singleton wrapper:
public class ActivityCache : ICache<string, Activity>
{
private readonly ICache<string, Activity> _cache = new Cache<string, Activity>();
private static readonly ActivityCache _instance = new ActivityCache();
// http://www.yoda.arachsys.com/csharp/singleton.html
static ActivityCache()
{
}
ActivityCache()
{
}
public static ActivityCache Instance
{
get { return _instance; }
}
public Activity this[string activityUrl]
{
get
{
if (string.IsNullOrEmpty(activityUrl))
{
return null;
}
return _cache[activityUrl];
}
set
{
if (string.IsNullOrEmpty(activityUrl))
{
return;
}
_cache[activityUrl] = value;
}
}
public ICollection<Activity> GetAll()
{
return _cache.GetAll();
}
public bool ContainsKey(string key)
{
return _cache.ContainsKey(key);
}
}
This is working fine (I haven't noticed/heard of any errors... yet :) ).
But now I have a problem. I need to reload the cache with new key/values.
Question 1.) Can I implement a "safe" reload method that reloads the cache (the Dictionary in the Cache class) ?
E.g:
public void Reload(IDictionary<TKey, TValue> values)
{
lock (_syncLock)
{
_internalCache.Clear();
foreach (KeyValuePair<TKey, TValue> value in values)
{
/* Problems can (will) occur if another
thread is calling the GetAll method... */
_internalCache[value.Key] = value.Value;
}
}
}
Question 2.) Should I use some IoC container or some other library instead?
Thanks!
Note: I'm using .NET 3.5
use ConcurrentDictionary, then you wont have to deal with Synchronization.
Also, you dont want to reload all the cache items as well. instead you want to do staggering, load the cache objects in the key/value store on demand.
You can use timestamp or some versioning for that. if you reload the data per each key/value pair then you wont have to lock the whole collection.
I really recommend you to use ConcurrentDictionary.
You should lock around GetAll as well.
You could use a double buffer type technique to make the reload less painful :
public void Reload(IDictionary<TKey, TValue> values)
{
cache = new Dictionary<TKey, TValue> ();
foreach (KeyValuePair<TKey, TValue> value in values)
{
cache[value.Key] = value.Value;
}
lock (_syncLock)
{
_internalCache = cache;
}
}
This will work providing you don't mind readers accessing potentially out of date information whilst you call reload.
I thought of solution below because the collection is very very small. But what if it was big?
private Dictionary<string, OfTable> _folderData = new Dictionary<string, OfTable>();
public Dictionary<string, OfTable> FolderData
{
get { return new Dictionary<string,OfTable>(_folderData); }
}
With List you can make:
public class MyClass
{
private List<int> _items = new List<int>();
public IList<int> Items
{
get { return _items.AsReadOnly(); }
}
}
That would be nice!
Thanks in advance, Cheers & BR - Matti
NOW WHEN I THINK THE OBJECTS IN COLLECTION ARE IN HEAP. SO MY SOLUTION DOES NOT PREVENT THE CALLER TO MODIFY THEM!!! CAUSE BOTH Dictionary s CONTAIN REFERENCES TO SAME OBJECT. DOES THIS APPLY TO List EXAMPLE ABOVE?
class OfTable
{
private int _table;
private List<int> _classes;
private string _label;
public OfTable()
{
_classes = new List<int>();
}
public int Table
{
get { return _table; }
set { _table = value; }
}
public List<int> Classes
{
get { return _classes; }
set { _classes = value; }
}
public string Label
{
get { return _label; }
set { _label = value; }
}
}
so how to make this immutable??
It's not difficult to roll your own ReadOnlyDictionary<K,V> wrapper class. Something like this:
public sealed class ReadOnlyDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
private readonly IDictionary<TKey, TValue> _dictionary;
public ReadOnlyDictionary(IDictionary<TKey, TValue> dictionary)
{
if (dictionary == null)
throw new ArgumentNullException("dictionary");
_dictionary = dictionary;
}
public bool ContainsKey(TKey key)
{
return _dictionary.ContainsKey(key);
}
public int Count
{
get { return _dictionary.Count; }
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return _dictionary.GetEnumerator();
}
public ICollection<TKey> Keys
{
get { return _dictionary.Keys; }
}
public bool TryGetValue(TKey key, out TValue value)
{
return _dictionary.TryGetValue(key, out value);
}
public ICollection<TValue> Values
{
get { return _dictionary.Values; }
}
public TValue this[TKey key] // Item
{
get { return _dictionary[key]; }
}
#region IDictionary<TKey, TValue> Explicit Interface Implementation
void IDictionary<TKey, TValue>.Add(TKey key, TValue value)
{
throw new NotSupportedException("Dictionary is read-only.");
}
bool IDictionary<TKey, TValue>.Remove(TKey key)
{
throw new NotSupportedException("Dictionary is read-only.");
}
TValue IDictionary<TKey, TValue>.this[TKey key] // Item
{
get { return _dictionary[key]; }
set { throw new NotSupportedException("Dictionary is read-only."); }
}
#endregion
#region ICollection<T> Explicit Interface Implementation
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
{
throw new NotSupportedException("Collection is read-only.");
}
void ICollection<KeyValuePair<TKey, TValue>>.Clear()
{
throw new NotSupportedException("Collection is read-only.");
}
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
{
return _dictionary.Contains(item);
}
void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
_dictionary.CopyTo(array, arrayIndex);
}
bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly
{
get { return true; }
}
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
{
throw new NotSupportedException("Collection is read-only.");
}
#endregion
#region IEnumerable Explicit Interface Implementation
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)_dictionary).GetEnumerator();
}
#endregion
}
If you're using C#3 or later then you could knock-up a matching AsReadOnly extension method too:
public static class ReadOnlyDictionaryHelper
{
public static ReadOnlyDictionary<TKey, TValue> AsReadOnly<TKey, TValue>(this IDictionary<TKey, TValue> dictionary)
{
var temp = dictionary as ReadOnlyDictionary<TKey, TValue>;
return temp ?? new ReadOnlyDictionary<TKey, TValue>(dictionary);
}
}
And then return the read-only wrapper from your property:
// in C#2
return new ReadOnlyDictionary<string, OfTable>(_folderData);
// in C#3 or later
return _folderData.AsReadOnly();
Use ReadOnlyCollection<T> class.
An instance of the ReadOnlyCollection generic class is always read-only. A collection that is read-only is simply a collection with a wrapper that prevents modifying the collection; therefore, if changes are made to the underlying collection, the read-only collection reflects those changes. See Collection for a modifiable version of this class.
--EDIT--
Checkout a trivial dictionary wrapper here. And A Generic Read-Only Dictionary by Richard Carr.