代码之家  ›  专栏  ›  技术社区  ›  Brent Arias

从字典中组合“检查添加或获取”

  •  4
  • Brent Arias  · 技术社区  · 14 年前

    我厌倦了这本字典的成语:

            Dictionary<Guid,Contact> Contacts;
            //...
            if (!Contacts.ContainsKey(id))
            {
                contact = new Contact();
                Contacts[id] = contact;
            }
            else
            {
                contact = Contacts[id];
            }
    

    如果有语法允许从默认构造函数隐式创建新值(如果不存在的话,字典知道值的类型),那就太好了。有人看到这样做的助手(如扩展方法)吗?

    3 回复  |  直到 14 年前
        1
  •  11
  •   Ani    14 年前

    public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> dictionary,
                                                TKey key, Func<TValue> valueCreator)
    {
        TValue value;
        if (!dictionary.TryGetValue(key, out value))
        {
            value = valueCreator();
            dictionary.Add(key, value);
        }
        return value;
    }
    
    public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> dictionary,
                                                TKey key) where TValue : new()
    {
       return dictionary.GetOrAdd(key, () => new TValue());
    }
    

    var contacts = new Dictionary<Guid, Contact>();
    Guid id = ...
    
    contacts.GetOrAdd(id).Name = "Abc"; // ok since Contact has public parameterless ctor
    contacts.GetOrAdd(id, () => new Contact { Name = "John Doe" }).Age = 40;
    
        2
  •  3
  •   Community CDub    8 年前

    /// <param name="valueCreator">The expensive value creator function.</param>
    public static T GetOrAdd<S, T>(this IDictionary<S, T> dict, S key, 
                                   Func<T> valueCreator)
    {
        T value;
        return dict.TryGetValue(key, out value) ? value : dict[key] = valueCreator();
    }
    

    doesn't have this feature out of the box to do all this in a single lookup

        3
  •  0
  •   Demetris Leptos    8 年前

    Func<K, T>
    

    IDictionary<K,T>
    

    public class WrappedDictionary<K, T> : IDictionary<K, T>
    {
        public IDictionary<K, T> WrappedInstance { get; set; }
    
        public virtual T this[K key]
        {
            get
            {
                // CUSTOM RESOLUTION CODE GOES HERE
                return this.WrappedInstance[key];
            }
            set
            {
                this.WrappedInstance[key] = value;
            }
        }
    
        public int Count
        {
            get
            {
                return this.WrappedInstance.Count;
            }
        }
    
        public bool IsReadOnly
        {
            get
            {
                return this.WrappedInstance.IsReadOnly;
            }
        }
    
        public ICollection<K> Keys
        {
            get
            {
                return this.WrappedInstance.Keys;
            }
        }
    
        public ICollection<T> Values
        {
            get
            {
                return this.WrappedInstance.Values;
            }
        }
    
        public void Add(KeyValuePair<K, T> item)
        {
            this.WrappedInstance.Add(item);
        }
    
        public void Add(K key, T value)
        {
            this.WrappedInstance.Add(key, value);
        }
    
        public void Clear()
        {
            this.WrappedInstance.Clear();
        }
    
        public bool Contains(KeyValuePair<K, T> item)
        {
            return this.WrappedInstance.Contains(item);
        }
    
        public bool ContainsKey(K key)
        {
            return this.WrappedInstance.ContainsKey(key);
        }
    
        public void CopyTo(KeyValuePair<K, T>[] array, int arrayIndex)
        {
            this.WrappedInstance.CopyTo(array, arrayIndex);
        }
    
        public IEnumerator<KeyValuePair<K, T>> GetEnumerator()
        {
            return this.WrappedInstance.GetEnumerator();
        }
    
        public bool Remove(KeyValuePair<K, T> item)
        {
            return this.WrappedInstance.Remove(item);
        }
    
        public bool Remove(K key)
        {
            return this.WrappedInstance.Remove(key);
        }
    
        public bool TryGetValue(K key, out T value)
        {
            // CUSTOM RESOLUTION CODE GOES HERE
            return this.WrappedInstance.TryGetValue(key, out value);
        }
    
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.WrappedInstance.GetEnumerator();
        }
    }