using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace miew.ReadOnly { public static class Extensions { static public IReadOnlyDictionary<TKey, TValue> ToReadOnlyDictionary<TSrc, TKey, TValue>( this IEnumerable<TSrc> ie, Func<TSrc, TKey> key_selector, Func<TSrc, TValue> value_selector) { return new ReadOnlyDictionary<TKey, TValue>(ie.ToDictionary(key_selector, value_selector)); } static public IReadOnlyDictionary<TKey, TValue> ToReadOnlyDictionary<TKey, TValue>(this IDictionary<TKey, TValue> d) { return new ReadOnlyDictionary<TKey, TValue>(d); } static public IReadOnlyCollection<T> ToReadOnlyCollection<T>(this IEnumerable<T> seq) { return new ReadOnlyCollection<T>(seq); } }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public struct DeferredCollection<T> : ICollection<T> { int c; IEnumerable<T> ie; public DeferredCollection(int c, IEnumerable<T> ie) { this.c = c; this.ie = ie; } public bool Contains(T item) { return ie.Contains(item); } public void CopyTo(T[] array, int arrayIndex) { foreach (T t in ie) array[arrayIndex++] = t; } public void Add(T item) { throw new NotImplementedException(); } public void Clear() { throw new NotImplementedException(); } public int Count { get { return c; } } public bool IsReadOnly { get { return true; } } public bool Remove(T item) { throw new NotImplementedException(); } public IEnumerator<T> GetEnumerator() { return ie.GetEnumerator(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return ie.GetEnumerator(); } }; public class ReadOnlyCollection<T> : IReadOnlyCollection<T>, ICollection<T> { T[] arr; public ReadOnlyCollection(IEnumerable<T> seq) { this.arr = seq as T[] ?? seq.ToArray(); } public int Count { get { return arr.Length; } } public T this[int ix] { get { return arr[ix]; } } public int IndexOf(T item) { return System.Array.IndexOf<T>(arr, item); } public bool Contains(T item) { return System.Array.IndexOf<T>(arr, item) != -1; } public void CopyTo(T[] array, int arrayIndex) { arr.CopyTo(array, arrayIndex); } public IEnumerator<T> GetEnumerator() { return arr.AsEnumerable<T>().GetEnumerator(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return arr.AsEnumerable<T>().GetEnumerator(); } public static explicit operator T[](ReadOnlyCollection<T> ro) { return ro.arr; } public static explicit operator ReadOnlyCollection<T>(T[] seq) { return new ReadOnlyCollection<T>(seq); } public bool IsReadOnly { get { return true; } } public void Add(T item) { throw new InvalidOperationException(); } public void Clear() { throw new InvalidOperationException(); } public bool Remove(T item) { throw new InvalidOperationException(); } }; public interface IReadOnlyCollection<T> : IEnumerable<T> { bool Contains(T item); void CopyTo(T[] array, int arrayIndex); int Count { get; } T this[int ix] { get; } int IndexOf(T item); }; public interface IReadOnlyDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>> { bool ContainsKey(TKey key); ICollection<TKey> Keys { get; } ICollection<TValue> Values { get; } int Count { get; } bool IsReadOnly { get; } bool TryGetValue(TKey key, out TValue value); TValue this[TKey key] { get; } } public class ReadOnlyDictionary<TKey, TValue> : IReadOnlyDictionary<TKey, TValue> { static ReadOnlyDictionary<TKey, TValue> _e = null; public static ReadOnlyDictionary<TKey, TValue> Empty { get { return _e = _e ?? new ReadOnlyDictionary<TKey, TValue>(); } } private IDictionary<TKey, TValue> _dict; public ReadOnlyDictionary() { _dict = new Dictionary<TKey, TValue>(); } public ReadOnlyDictionary(IDictionary<TKey, TValue> dictionary) { _dict = dictionary; } public bool ContainsKey(TKey key) { return _dict.ContainsKey(key); } public ICollection<TKey> Keys { get { return _dict.Keys; } } public bool TryGetValue(TKey key, out TValue value) { return _dict.TryGetValue(key, out value); } public ICollection<TValue> Values { get { return _dict.Values; } } public TValue this[TKey key] { get { return _dict[key]; } } public bool Contains(KeyValuePair<TKey, TValue> item) { return _dict.Contains(item); } public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) { _dict.CopyTo(array, arrayIndex); } public int Count { get { return _dict.Count; } } public bool IsReadOnly { get { return true; } } public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() { return _dict.GetEnumerator(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } }; public struct CovariantCollectionWrapper<TOut, TIn> : ICollection<TOut> where TIn : TOut { readonly ICollection<TIn> coll; public CovariantCollectionWrapper(ICollection<TIn> coll) { this.coll = coll; } public bool Contains(TOut item) { return item is TIn && coll.Contains((TIn)item); } public void CopyTo(TOut[] array, int arrayIndex) { foreach (TOut t in this) array[arrayIndex++] = t; } public int Count { get { return coll.Count; } } public bool IsReadOnly { get { return true; } } public IEnumerator<TOut> GetEnumerator() { foreach (TIn t in coll) yield return t; } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } public void Add(TOut item) { throw new InvalidOperationException(); } public void Clear() { throw new InvalidOperationException(); } public bool Remove(TOut item) { throw new InvalidOperationException(); } }; public struct CovariantListWrapper<TOut, TIn> : IList<TOut> where TIn : TOut { readonly IList<TIn> list; public CovariantListWrapper(IList<TIn> list) { this.list = list; } public int IndexOf(TOut item) { // (not covariant but permitted) return item is TIn ? list.IndexOf((TIn)item) : -1; } public TOut this[int index] { get { return list[index]; } set { throw new InvalidOperationException(); } } public bool Contains(TOut item) { // (not covariant but permitted) return item is TIn && list.Contains((TIn)item); } public void CopyTo(TOut[] array, int arrayIndex) { foreach (TOut t in this) array[arrayIndex++] = t; } public int Count { get { return list.Count; } } public bool IsReadOnly { get { return true; } } public IEnumerator<TOut> GetEnumerator() { foreach (TIn t in list) yield return t; } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } public void Insert(int index, TOut item) { throw new InvalidOperationException(); } public void RemoveAt(int index) { throw new InvalidOperationException(); } public void Add(TOut item) { throw new InvalidOperationException(); } public void Clear() { throw new InvalidOperationException(); } public bool Remove(TOut item) { throw new InvalidOperationException(); } } public class CovariantDictionaryWrapper<TKey, TOut, TIn> : IReadOnlyDictionary<TKey, TOut> where TIn : TOut { private IDictionary<TKey, TIn> _dict; private ICollection<TOut> values = null; public CovariantDictionaryWrapper(IDictionary<TKey, TIn> dictionary) { _dict = dictionary; } public bool ContainsKey(TKey key) { return _dict.ContainsKey(key); } public ICollection<TKey> Keys { get { return _dict.Keys; } } public bool TryGetValue(TKey key, out TOut value) { TIn v; if (!_dict.TryGetValue(key, out v)) { value = default(TOut); return false; } value = v; return true; } public ICollection<TOut> Values { get { return values = values ?? new CovariantCollectionWrapper<TOut, TIn>(_dict.Values); } } public TOut this[TKey key] { get { return _dict[key]; } } public bool Contains(KeyValuePair<TKey, TOut> item) { if (!(item.Value is TIn)) return false; return _dict.Contains(new KeyValuePair<TKey, TIn>(item.Key, (TIn)item.Value)); } public void CopyTo(KeyValuePair<TKey, TOut>[] array, int arrayIndex) { foreach (var kvp in this) array[arrayIndex++] = kvp; } public int Count { get { return _dict.Count; } } public bool IsReadOnly { get { return true; } } public IEnumerator<KeyValuePair<TKey, TOut>> GetEnumerator() { foreach (var kvp in _dict) yield return new KeyValuePair<TKey, TOut>(kvp.Key, kvp.Value); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } }; }