I'm trying to expose a read-only dictionary that holds objects with a read-only interface. Internally, the dictionary is write-able, and so are the objects within (see below example code). My problem is that IReadOnlyDictionary doesn't support covariant conversions because of the reason outlined in the question here. This means I can't just expose my internal dictionary as a read only one.
So my question is, is there an efficient way to convert my internal dictionary to an IReadOnlyDictionary, or some other way to handle this? The options I can think of are:
1 seems like a pain, 2 seems highly inefficient. 3 sounds like the most promising at the moment, but is still ugly. Do I have any other options?
public class ExposesReadOnly { private Dictionary<int, NotReadOnly> InternalDict { get; set; } public IReadOnlyDictionary<int, IReadOnly> PublicList { get { // This doesn't work... return this.InternalDict; } } // This class can be modified internally, but I don't want // to expose this functionality. private class NotReadOnly : IReadOnly { public string Name { get; set; } } } public interface IReadOnly { string Name { get; } }
You could write your own read-only wrapper for the dictionary, e.g.:
public class ReadOnlyDictionaryWrapper<TKey, TValue, TReadOnlyValue> : IReadOnlyDictionary<TKey, TReadOnlyValue> where TValue : TReadOnlyValue { private IDictionary<TKey, TValue> _dictionary; public ReadOnlyDictionaryWrapper(IDictionary<TKey, TValue> dictionary) { if (dictionary == null) throw new ArgumentNullException("dictionary"); _dictionary = dictionary; } public bool ContainsKey(TKey key) { return _dictionary.ContainsKey(key); } public IEnumerable<TKey> Keys { get { return _dictionary.Keys; } } public bool TryGetValue(TKey key, out TReadOnlyValue value) { TValue v; var result = _dictionary.TryGetValue(key, out v); value = v; return result; } public IEnumerable<TReadOnlyValue> Values { get { return _dictionary.Values.Cast<TReadOnlyValue>(); } } public TReadOnlyValue this[TKey key] { get { return _dictionary[key]; } } public int Count { get { return _dictionary.Count; } } public IEnumerator<KeyValuePair<TKey, TReadOnlyValue>> GetEnumerator() { return _dictionary .Select(x => new KeyValuePair<TKey, TReadOnlyValue>(x.Key, x.Value)) .GetEnumerator(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return this.GetEnumerator(); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With