How to get IDictionaryEnumerator from generic IDictionary? - c#

I have a dictionary as follows:
IDictionary<string, string> dict;
How to create an enumerator that implements IDictionaryEnumerator (preferably using linq)?

Must be missing something here, what about:
IDictionary obsoleteDict = dict as IDictionary;
if (obsoleteDict == null)
{
//Do something here...
}
else
{
return obsoleteDict.GetEnumerator();
}
(edit: yep, you have to cast it to the old non-generic interface)
edit2: see Pavel's comment below. A type implementing IDictionary<K,V> may or may not implement IDictionary (Dictionary<K,V> does while some implementations like WCF's MessageProperties do not) so the cast may not work.

IDictionaryEnumerator is really the pre-generics version; you should just be able to use IEnumerator<KeyValuePair<string,string>>...
You could encapsulate, of course; this will then work even for custom implementations:
using System;
using System.Collections;
using System.Collections.Generic;
static class Program
{
class MyEnumerator<TKey,TValue> : IDictionaryEnumerator, IDisposable
{
readonly IEnumerator<KeyValuePair<TKey, TValue>> impl;
public void Dispose() { impl.Dispose(); }
public MyEnumerator(IDictionary<TKey, TValue> value)
{
this.impl = value.GetEnumerator();
}
public void Reset() { impl.Reset(); }
public bool MoveNext() { return impl.MoveNext(); }
public DictionaryEntry Entry { get { var pair = impl.Current;
return new DictionaryEntry(pair.Key, pair.Value);} }
public object Key { get { return impl.Current.Key; } }
public object Value { get { return impl.Current.Value; } }
public object Current {get {return Entry;}}
}
static IDictionaryEnumerator GetBasicEnumerator<TKey,TValue>(
this IDictionary<TKey, TValue> data)
{
return new MyEnumerator<TKey, TValue>(data);
}
static void Main()
{
IDictionary<int, string> data = new Dictionary<int, string>()
{
{1,"abc"}, {2,"def"}
};
IDictionaryEnumerator basic;
using ((basic = data.GetBasicEnumerator()) as IDisposable)
{
while (basic.MoveNext())
{
Console.WriteLine(basic.Key + "=" + basic.Value);
}
}
}
}

I believe that IDictionaryEnumerator is only implemented by non-generic dictionary types. The generic dictionary classes expose IEnumerator.
Since generic dictionaries return strongly typed KeyValuePair items, the features of IDictionaryEnumerator seem redundant. You should try to adapt your code if possible to just use IEnumerator<KeyValuePair<K,V>>.

In most cases, this will work. Then ones where it doesn't will throw an exception.
return (IDictionaryEnumerator)dict.GetEnumerator();
At least the following BCL types return enumerators that implement IDictionaryEnumerator (these are the ones I checked):
Hashtable (public API enforced)
Dictionary<T,K> (public API enforced)
SortedList<T,K> (not guaranteed by the public API, but the implementation does implement it)

Related

Dictionary extension method for specfic value type? e.g. Dictionary<T, List<U>>

Is it possible to write an extension method that works only with dictionaries that have a List as value?
I want to write one that checks if the key is existent, it will add another entry to the list. And if the key is not existent a new list is initialized, the entry added, and then everything added to the dictionary.
Now I am not sure what the method head looks like or if it is even possible to limit the function to a specific value type.
Yes, of course. In the extension method defintition you use List<T>, which the T defined in the type arguments. In this case named TListValue to avoid ambiguity:
public static void DoSomething<TKey, TListValue>(this Dictionary<TKey, List<TListValue>> dictionary)
{
...
}
You can use it without specifying the type parameters. They should be infered:
Dictionary<string, List<string>> u = new Dictionary<string, List<string>>();
u.DoSomething();
Here is a sample implementation of the method that you want to write:
static class DictExtensions {
public static void Insert<TKey,TVal>(this IDictionary<TKey,List<TVal>> d, TKey k, TVal v) {
List<TVal> current;
if (!d.TryGetValue(k, out current)) {
d.Add(k, new List<TVal> { v } );
} else {
current.Add(v);
}
}
}
The name Add would collide with the instance method of Dictionary, so I used the name Insert.
Demo.
Rather than an extension method, I would personally create a class inheriting from Dictionary:
public class ListDictionary<TKey, TValue> : Dictionary<TKey, List<TValue>>
{
new public List<TValue> this[TKey index]
{
get
{
List<TValue> list = null;
if (!TryGetValue(index, out list))
{
list = new List<TValue>();
Add(index, list);
}
return list;
}
set
{
if (ContainsKey(index))
base[index] = value;
else
Add(index, value);
}
}
}
Usage:
ListDictionary<string, string> dictionary = new ListDictionary<string, string>();
dictionary["list1"].Add("item1"); // list will be initialised here
dictionary["list1"].Add("item2");
dictionary["list2"].Add("item1"); // and another

Dictionary containing with only Serializable objects

I am looking for a way to ensure that only serializable objects are stored into a Dictionary in C#.
To be more specific I'm looking to do something similar to this:
Dictionary<String, ISerializable> serialDict = new Dictionary<String, ISerializable>();
The problem with this is that I cannot store primitive types like integers, booleans, or strings.
Is there a way to ensure that my Dictionary contains only objects which can be serialized?
I don't think you can do this at compile-time, but you can do it at runtime. If you build your own class deriving from Dictionary<TKey, TValue>, then in the constructor of your class, you can check the attributes attached to the TValue type, and make sure SerializableAttribute is one of them, else throw an exception.
All of the standard primitive types (int, bool, etc.) have this attribute.
One thing to consider is that in classes that are serializable are tagged with the SerializableAttribute as opposed to implementing an interface. From MSDN:
Any class that might be serialized must be marked with the
SerializableAttribute. If a class needs to control its serialization
process, it can implement the ISerializable interface.
What you would need to do is make your own class that implements the IDictioanry interface and every time someone calls add, use reflection to check if the element passed in has a serializable attribute (and throw an exception if it doesn't).
Code would look something like
class MyDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
private Dictionary<TKey, TValue> d;
public void Add(TKey key, TValue value)
{
if( value.GetType().IsSerializable )
{
d.Add(key, value);
}
else
{
throw new ArgumentException();
}
}
.....
}
[Serializable]
public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>
{
static SerializableDictionary()
{
AssertSerializable(typeof(TKey));
AssertSerializable(typeof(TValue));
}
static void AssertSerializable(Type t)
{
if (!t.IsSerializable)
{
throw new NotSupportedException(string.Format(
"{0} is not serializable", t.Name));
}
}
}
One answer would be to create a SerializablePrimative wrapper class.
class SerializablePrimative<T> : ISerializable {
private T val = default();
private SerializablePrimative(T newVal){
val = newVal;
}
public static boolean IsSupported(Object o){
if (o == null){
return false;
}else{
return IsSupported(o.GetType());
}
}
public static boolean IsSupported(Type t){
if (// you want to support* ...)
{
return true;
}
else
{
return false;
}
}
public static SerializablePrimative GetSerializable(Object o){
if (IsSupported(o)){
return //Intstatiate via Reflection **
}else {
return null;
}
}
}
The rest is left as an exercise to the reader, but basically your creating an adapter to make these certain types "fit" your dictionary.
*See Also: Types Supported by the Data Contract Serializer
**See Also: C#: Using Reflection to Instantiate a Generic Class in .Net
What about wrapping your dictionary?
class SomeClass {
Dictionary<string,object> d;
// add ISerializable
public void Add(string key, ISerializable value) {
d[key] = value;
}
// add primitive types
public void Add(string key, bool value) {
d[key] = value;
}
public void Add(string key, int value) {
d[key] = value;
}
// etc ...
}
In this way you are sure that only ISerializable objects and primitive types can be added.

Generic Key/Value pair collection in that preserves insertion order?

I'm looking for something like a Dictionary<K,V> however with a guarantee that it preserves insertion order. Since Dictionary is a hashtable, I do not think it does.
Is there a generic collection for this, or do I need to use one of the old .NET 1.1 collections?
There is not. However, System.Collections.Specialized.OrderedDictionary should solve most need for it.
EDIT: Another option is to turn this into a Generic. I haven't tested it but it compiles (C# 6) and should work. However, it will still have the same limitations that Ondrej Petrzilka mentions in comments below.
public class OrderdDictionary<T, K>
{
public OrderedDictionary UnderlyingCollection { get; } = new OrderedDictionary();
public K this[T key]
{
get
{
return (K)UnderlyingCollection[key];
}
set
{
UnderlyingCollection[key] = value;
}
}
public K this[int index]
{
get
{
return (K)UnderlyingCollection[index];
}
set
{
UnderlyingCollection[index] = value;
}
}
public ICollection<T> Keys => UnderlyingCollection.Keys.OfType<T>().ToList();
public ICollection<K> Values => UnderlyingCollection.Values.OfType<K>().ToList();
public bool IsReadOnly => UnderlyingCollection.IsReadOnly;
public int Count => UnderlyingCollection.Count;
public IDictionaryEnumerator GetEnumerator() => UnderlyingCollection.GetEnumerator();
public void Insert(int index, T key, K value) => UnderlyingCollection.Insert(index, key, value);
public void RemoveAt(int index) => UnderlyingCollection.RemoveAt(index);
public bool Contains(T key) => UnderlyingCollection.Contains(key);
public void Add(T key, K value) => UnderlyingCollection.Add(key, value);
public void Clear() => UnderlyingCollection.Clear();
public void Remove(T key) => UnderlyingCollection.Remove(key);
public void CopyTo(Array array, int index) => UnderlyingCollection.CopyTo(array, index);
}
There actually is one, which is generic and has been around since .net 2.0. It's called KeyedCollection<TKey, TItem>. However, it comes with the restriction that it constructs the keys from the values, so it is not a generic Key/Value pair collection. (Although you can of course use it like KeyedCollection<TKey, Tuple<TKey, TItem>> as a workaround).
If you need it as an IDictionary<TKey, TItem>, it has a .Dictionary property.
A somewhat minor issue that I have with it is that it is an abstract class and you have to subclass it and implement:
protected abstract TKey GetKeyForItem(TItem item)
I'd rather just pass a lambda into the constructor for this purpose, but then again, I guess a virtual method is slightly faster than a lambda (any comments on this appreciated).
Edit As the question came up in the comments: KeyedCollection preserves order, as it inherits from Collection<T>, which does (it derives from IList<T>. See also the documentation of the Add method: Adds an object to the end of the Collection.).
There is an OrderedDictionary class that is a dictionary but can be indexed in insertion order, but it is not generified. There is not a generified one in the .Net framework at present.
I have read a comment somewhere from someone on the .Net team that said that they may implement a generified version in the future, but if so it would most likely be called IndexableDictionary instead of OrderedDictionary to make its behaviour more obvious.
EDIT: found the quote. It was on the MSDN page for OrderedDictionary, attributed to David M. Kean from Microsoft:
This type is actually misnamed; it is not an 'ordered' dictionary as such, but rather an 'indexed' dictionary. Although, today there is no equivalent generic version of this type, if we add one in the future it is likely that we will name such as type 'IndexedDictionary'.
Here is a wrapper for the non-generic Systems.Collections.Specialized.OrderedDictionary type.
This type will return keys/value/pairs sequences in insertion order, much like Ruby 2.0 hashes.
It does not require C#6 magic, conforms to IDictionary<TKey,TValue> (which also means that accessing a non-assigned key throws an exception), and ought to be serializable.
It is given the name 'IndexedDictionary' per note on Adrian's answer.
YMMV.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
/// <summary>
/// A dictionary that maintains insertion ordering of keys.
///
/// This is useful for emitting JSON where it is preferable to keep the key ordering
/// for various human-friendlier reasons.
///
/// There is no support to manually re-order keys or to access keys
/// by index without using Keys/Values or the Enumerator (eg).
/// </summary>
[Serializable]
public sealed class IndexedDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
// Non-generic version only in .NET 4.5
private readonly OrderedDictionary _backing = new OrderedDictionary();
private IEnumerable<KeyValuePair<TKey, TValue>> KeyValuePairs
{
get
{
return _backing.OfType<DictionaryEntry>()
.Select(e => new KeyValuePair<TKey, TValue>((TKey)e.Key, (TValue)e.Value));
}
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return KeyValuePairs.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Add(KeyValuePair<TKey, TValue> item)
{
_backing[item.Key] = item.Value;
}
public void Clear()
{
_backing.Clear();
}
public bool Contains(KeyValuePair<TKey, TValue> item)
{
return _backing.Contains(item.Key);
}
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
KeyValuePairs.ToList().CopyTo(array, arrayIndex);
}
public bool Remove(KeyValuePair<TKey, TValue> item)
{
TValue value;
if (TryGetValue(item.Key, out value)
&& Equals(value, item.Value))
{
Remove(item.Key);
return true;
}
return false;
}
public int Count
{
get { return _backing.Count; }
}
public bool IsReadOnly
{
get { return _backing.IsReadOnly; }
}
public bool ContainsKey(TKey key)
{
return _backing.Contains(key);
}
public void Add(TKey key, TValue value)
{
_backing.Add(key, value);
}
public bool Remove(TKey key)
{
var result = _backing.Contains(key);
if (result) {
_backing.Remove(key);
}
return result;
}
public bool TryGetValue(TKey key, out TValue value)
{
object foundValue;
if ((foundValue = _backing[key]) != null
|| _backing.Contains(key))
{
// Either found with a non-null value, or contained value is null.
value = (TValue)foundValue;
return true;
}
value = default(TValue);
return false;
}
public TValue this[TKey key]
{
get
{
TValue value;
if (TryGetValue(key, out value))
return value;
throw new KeyNotFoundException();
}
set { _backing[key] = value; }
}
public ICollection<TKey> Keys
{
get { return _backing.Keys.OfType<TKey>().ToList(); }
}
public ICollection<TValue> Values
{
get { return _backing.Values.OfType<TValue>().ToList(); }
}
}
I know you're writing C#, but Java has a class called LinkedHashMap that uses a private LinkedList to maintain the order of insertion of keys. If you can't find a suitable generic solution, perhaps that would be a start on implementing your own.
Another option for a Generic Key/Value pair that preserves insertion is to use something like:
Queue<KeyValuePair<string, string>>
This would be a guaranteed ordered list. You can en-queue and dequeue in an ordered faction similar to Add/Remove of dictionary as opposed to resizing an Array. It can often serve as a middle ground between a non-resizing ordered (by insertion) array and an autoresizing unordered (by insertion) list.
If you need constant complexity of Add, Remove, ContainsKey and order preservation, then there's no such generic in .NET Framework 4.5.
If you're okay with 3rd party code, take a look at my repository (permissive MIT license):
https://github.com/OndrejPetrzilka/Rock.Collections
There's OrderedDictionary<K,V> collection:
source code based on classic Dictionary<K,V> (from .NET Core)
preserves order of insertions and allows manual reordering
features reversed enumeration
has same operation complexities as Dictionary<K,V>
Add and Remove operations are ~20% slower compared to Dictionary<K,V>
consumes 8 more bytes of memory per item
Code:
//A SortedDictionary is sorted on the key (not value)
System.Collections.Generic.SortedDictionary<string, string> testSortDic = new SortedDictionary<string, string>();
//Add some values with the keys out of order
testSortDic.Add("key5", "value 1");
testSortDic.Add("key3", "value 2");
testSortDic.Add("key2", "value 3");
testSortDic.Add("key4", "value 4");
testSortDic.Add("key1", "value 5");
//Display the elements.
foreach (KeyValuePair<string, string> kvp in testSortDic)
{
Console.WriteLine("Key = {0}, value = {1}", kvp.Key, kvp.Value);
}
Output:
Key = key1, value = value 5
Key = key2, value = value 3
Key = key3, value = value 2
Key = key4, value = value 4
Key = key5, value = value 1

Is there a better data structure than Dictionary if the values are objects and a property of those objects are the keys?

I have a Dictionary<int, object> where the int is a property of obj. Is there a better data structure for this? I feel like using a property as the key is redundant.
This Dictionary<int, obj> is a field in a container class that allows for random indexing into the obj values based on an int id number. The simplified (no exception handling) indexer in the container class would look like:
obj this[int id]
{
get{ return this.myDictionary[id];}
}
where myDictionary is the aforementioned Dictionary<int, obj> holding the objects.
This may be the typical way of quick random access but I wanted to get second opinions.
There's no concrete class in the framework that does this. There's an abstract one though, KeyedCollection. You'll have to derive your own class from that one and implement the GetKeyForItem() method. That's pretty easy, just return the value of the property by which you want to index.
That's all you need to do, but do keep an eye on ChangeItemKey(). You have to do something meaningful when the property that you use as the key changes value. Easy enough if you ensure that the property is immutable (only has a getter). But quite awkward when you don't, the object itself now needs to have awareness of it being stored in your collection. If you don't do anything about it (calling ChangeItemKey), the object gets lost in the collection, you can't find it back. Pretty close to a leak.
Note how Dictionary<> side-steps this problem by specifying the key value and the object separately. You may still not be able to find the object back but at least it doesn't get lost by design.
There is a KeyedCollection class.
EDIT: The KeyedCollection can use a dictionary internally, but it cleaner interface for this particular scenario than a raw dictionary since you can lookup by values directly. Admittedly I don't find it very useful in general.
You can implement your own KeyedCollection trivially if the extra overhead that comes with the factory settings isn't worth it. The original KeyedCollection in System.Collections.ObjectModel is internally a Dictionary<TKey, TItem> and a List<TItem> which means you can have operations defined on both IList<> and IDictionary<>. For e.g., you can insert, access by index, traverse collection in the inserted order (all which IList<> facilitates) and at the same time you can have quick lookups based on key (with the help of dictionary). This means that when you're adding or removing an item they have to be performed on both underlying collections, apart from the small memory overhead to hold the extra List<> (but the objects are not duplicated as such). Though the addition speeds are not affected much (List<> addition is O(1)), removal speed is affected a little.
If you don't care about insertion order and accessing by index:
public class KeyedCollection<TKey, TItem> : ICollection<TItem>
{
MemberInfo _keyInfo;
Func<TItem, TKey> _keySelector;
Dictionary<TKey, TItem> _dict;
public TItem this[TKey key]
{
get { return _dict[key]; }
}
public int Count
{
get { return _dict.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
public ICollection<TKey> Keys
{
get { return _dict.Keys; }
}
private ICollection<TItem> Items
{
get { return _dict.Values; }
}
public KeyedCollection(Expression<Func<TItem, TKey>> keySelector, IEqualityComparer<TKey> comparer = null)
{
var keyExpression = keySelector.Body as MemberExpression;
if (keyExpression != null)
_keyInfo = keyExpression.Member;
_keySelector = keySelector.Compile();
_dict = new Dictionary<TKey, TItem>(comparer);
}
private TKey GetKeyForItem(TItem item)
{
return _keySelector(item);
}
public bool ContainsKey(TKey key)
{
return _dict.ContainsKey(key);
}
public bool Contains(TItem item)
{
return ContainsKey(GetKeyForItem(item));
}
public bool TryGetItem(TKey key, out TItem item)
{
return _dict.TryGetValue(key, out item);
}
public void Add(TItem item)
{
_dict.Add(GetKeyForItem(item), item);
}
public void AddOrUpdate(TItem item)
{
_dict[GetKeyForItem(item)] = item;
}
public bool UpdateKey(TKey oldKey, TKey newKey)
{
TItem oldItem;
if (_keyInfo == null || !TryGetItem(oldKey, out oldItem) || !SetItem(oldItem, newKey)) // important
return false;
RemoveKey(oldKey);
Add(oldItem);
return true;
}
private bool SetItem(TItem item, TKey key)
{
var propertyInfo = _keyInfo as PropertyInfo;
if (propertyInfo != null)
{
if (!propertyInfo.CanWrite)
return false;
propertyInfo.SetValue(item, key, null);
return true;
}
var fieldInfo = _keyInfo as FieldInfo;
if (fieldInfo != null)
{
if (fieldInfo.IsInitOnly)
return false;
fieldInfo.SetValue(item, key);
return true;
}
return false;
}
public bool RemoveKey(TKey key)
{
return _dict.Remove(key);
}
public bool Remove(TItem item)
{
return RemoveKey(GetKeyForItem(item));
}
public void Clear()
{
_dict.Clear();
}
public void CopyTo(TItem[] array, int arrayIndex)
{
Items.CopyTo(array, arrayIndex);
}
public IEnumerator<TItem> GetEnumerator()
{
return Items.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
I have implemented ICollection<TItem> to make it more standard compliant - and also you get the nice collection initializer syntax! :)
A sample usage:
var p1 = new Person { Name = "a" };
var p2 = new Person { Name = "b" };
var people = new KeyedCollection<string, Person>(p => p.Name) { p1, p2 };
// p1 == people["a"];
// p2 == people["b"];
C# dynamic properties post seems to show that using a Dictionary was a popular choice. The other posts suggest using a HashTable
Dictionary vs Hashtable

C# Indexer Property Question

I have a class like this:
public class SomeClass
{
private const string sessionKey = "__Privileges";
public Dictionary<int, Privilege> Privileges
{
get
{
if (Session[sessionKey] == null)
{
Session[sessionKey] = new Dictionary<int, Privilege>();
}
return (Dictionary<int, Privilege>)Session[sessionKey];
}
}
}
Now, if Ido this...
var someClass = new SomeClass();
var p = someClass.Privileges[13];
... and there is no key 13, I will get an error like this:
The given key was not present in the dictionary.
I would like to have a property that can be accessed in the same way as above, but will return a default object in case of the absence of the key.
I tried creating an indexer property like this...
public Privilege Privileges[int key]
{
get
{
try { return _privileges[key]; }
catch { return new Privilege(); }
}
}
... but it looks like that's not a C# 2008 language feature.
How can I access the property in the same way, but get the default object if the key isn't present?
C# does not supported named indexers, as you have discovered.
Have you considered using a regular method instead of an indexer property? Not every programming problem requires the use fancy syntax to solve. Yes, you could create your own IDictionary implementation with an aggregated dictionary and change the property access behavior - but is that really necessary for something that just fetches a value or returns a default?
I would add a method like this to your class:
protected Privilege GetPrivilege(int key)
{
try { return _privileges[key]; }
catch { return new Privilege(); }
}
or better yet, avoid exception handling as a flow control mechanism:
protected Privilege GetPrivilge( int key )
{
Privilege priv;
if( _privileges.TryGetValue( key, out priv ) )
return priv;
else
return new Privilege();
}
You'll have to define your own IDictionary-based class with an indexer that has the desired behavior, and return an instance of that, rather than the stock Dictionary class, in your property getter.
Indexers in C# can only be used with the this keyword.
I suspect you want something like this:
public Privilege this[int key]
{
get
{
try { return _privileges[key]; }
catch { return default(Privelege); }
}
}
which you can define either directly in SomeClass so that you can access a privelege item like:
SomeClass foo;
var bar = foo[100];
or define this indexer in a custom class that implements from IDictionary<TKey, TValue> (and contains a Dictionary<TKey, TValue internally for actually storing the data). You could then use it like:
SomeClass foo;
var bar = foo.Priveleges[100];
Which is the syntax you seem to propose, and which may be most appropiate, though it takes a bit more effort.
You should use this syntax to retrieve the value:
public Privilege this[int key]
{
get
{
var value = (Privilege)null;
if(!_privileges.TryGetValue(key, out value))
value = new Privilege();
return value;
}
}
I have a need for this kind of use of IDictionary a lot, so I made some extension methods:
public static TValue Get<TKey, TValue>(this IDictionary<TKey, TValue> d, TKey key)
{
TValue v = default(TValue);
d.TryGetValue(key, out v);
return v;
}
public static TValue Get<TKey, TValue>(this IDictionary<TKey, TValue> d, TKey key, Func<TValue> value)
{
TValue v = d.Get(key);
if (v == null)
{
v = value();
d.Add(key, v);
}
return v;
}
Now you could write:
public Privilege this[int key]
{
get
{
return _privileges.Get(key, () => new Privilege());
}
}

Categories

Resources