您当前的位置: 首页 > 

寒冰屋

暂无认证

  • 1浏览

    0关注

    2286博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

NameValueCollection的泛型形式

寒冰屋 发布时间:2022-07-19 19:00:00 ,浏览量:1

目录

介绍

背景

类定义

基本方法

属性

集合枚举

用法

下载源代码 - 4.6 KB

介绍

内置在mscorlib中的NameValueCollection实现是一个类似于Dictionary的集合,但NameValueCollection可以有重复的键,而Dictionary不能。元素可以通过索引和键获得。这个集合的特别之处在于,一个键可以包含多个元素,并且允许null作为键或值。但是有一个小问题。NameValueCollection假定字符串用作键和值。那么如果你想存储任何类型的值,而不仅仅是字符串呢?? 当然,您可以在每次获取值时将文本转换为所需的类型,但是这里有三个重要的限制:

  1. 转换的处理开销;
  2. 并非所有类型都支持与字符串的转换;
  3. 不保留对原始对象的引用。
背景

NameValueCollection集合基于NameObjectCollectionBase——关联字符串键和对象值集合的基类,其中包含访问值的基本方法。接口IDictionary,IEnumerable在类中实现为额外的可用性。

类定义

第一次,定义包含键和值的类及其成员。私有字段将包含指定数组中的缓存数据。该InvalidateCachedArrays方法将重置缓存并在每次数据更改时调用。

public partial class NameValueCollection : NameObjectCollectionBase
{
    private string[] _keys; // Cached keys.
    private T[] _values;    // Cached values.

    // Resets the caches.
    protected void InvalidateCachedArrays()
    {
        _values = null;
        _keys = null;
    }
}

基本方法

下一步,是时候添加可以使用基类方法获取、设置和删除集合中数据的类方法了。

Add和Set方法将接收到的值放入与指定键配对的列表中。

public partial class NameValueCollection
{
    // Adds single value to collection.
    public void Add(string name, T value)
    {
        InvalidateCachedArrays();
        List list = BaseGet(name) as List;
        if (list == null)
        {
            list = new List(1) {value};
            BaseAdd(name, list);
        }
        else
        {
            if (value == null) return;
            list.Add(value);
        }
    }

    // Adds range of values to collection.
    public void Add(NameValueCollection collection)
    {
        InvalidateCachedArrays();
        int count = collection.Count;
        for (int i = 0; i < count; i++)
        {
            string key = collection.GetKey(i);
            T[] values = collection.Get(i);
            foreach (var value in values)
            {
                Add(key, value);
            }
        }
    }

    // Set single value (previous values will be removed).
    public void Set(string name, T value)
    {
        InvalidateCachedArrays();
        BaseSet(name, new List(1){value});
    }

    // Set range of values (previous values will be removed).
    public void Set(string name, params T[] values)
    {
        InvalidateCachedArrays();
        BaseSet(name, new List(values));
    }
}

GetKey和Get方法返回请求的键和与键值关联的数组。无论它们配对的键如何,GetAllValues都返回所有值,这些方法在将来很有用。

public partial class NameValueCollection
{
    // Gets all values cache.
    protected T[] GetAllValues()
    {
        int count = Count;
        List list = new List(count);
        for (int i = 0; i < count; ++i)
        {
            list.AddRange(Get(i));
        }
        return list.ToArray();
    }

    // Gets all values that paired with specified key.
    public T[] Get(string name)
    {
        return ((List)BaseGet(name)).ToArray();
    }

    // Gets all values at the specified index of collection.
    public T[] Get(int index)
    {
        return ((List)BaseGet(index)).ToArray();
    }

    // Gets string containing the key at the specified index.
    public string GetKey(int index)
    {
        return BaseGetKey(index);
    }
}

Clear和Remove方法从集合中删除值。

public partial class NameValueCollection
{
    // Removes values from the specified key.
    public void Remove(string name)
    {
        InvalidateCachedArrays();
        BaseRemove(name);
    }

    // Removes all data from the collection.
    public void Clear()
    {
        InvalidateCachedArrays();
        BaseClear();
    }
}

属性

快完成了!为了使这个集合更易于使用,添加属性是一个好主意。Keys和Values属性尝试返回缓存数据并在缓存失效时对其进行更新。

public partial class NameValueCollection
{
    // All keys that the current collection contains.
    public string[] Keys
    {
        get
        {
            if (_keys == null)
                _keys = BaseGetAllKeys();
            return _keys;
        }
    }

    // All values that the current collection contains.
    public T[] Values
    {
        get
        {
            if (_values == null)
                _values = GetAllValues();
            return _values;
        }
    }

    // Values at the specified index.
    public T[] this[int index]
    {
        get
        {
            return Get(index);
        }
        set
        {
            BaseSet(index, new List(value));
        }
    }

    // Values at the specified key.
    public T[] this[string name]
    {
        get
        {
            return Get(name);
        }
        set
        {
            BaseSet(name, new List(value));
        }
    }
}

集合枚举

嵌入类Enumerator将负责枚举集合中的所有键值对。该GetAllEntries方法返回枚举器使用的所有键值对。

public partial class NameValueCollection
{
    // Enumerates all entries.
    protected IEnumerable GetAllEntries()
    {
        return
            from key in Keys
            from value in Get(key)
            select new KeyValuePair(key, value);
    }

    // The enumerator that can enumerate all entries in the collection.

    private class Enumerator : IEnumerator, IDictionaryEnumerator
    {
        // Enumerate all entries in collection.
        private readonly IEnumerator _enumerator;

        // Initialize the enumerator.
        public Enumerator(NameValueCollection collection)
        {
            IEnumerable entries =
                collection.GetAllEntries().ToArray();
            _enumerator = entries.GetEnumerator();
        }

        // Returns the element of the collection corresponding
        // to the current position of the enumerator.
        KeyValuePair IEnumerator.Current
        {
            get { return _enumerator.Current; }
        }

        // Returns the object of the collection corresponding
        // to the current position of the enumerator.
        object IEnumerator.Current
        {
            get
            {
                IEnumerator enumerator = ((IEnumerator) _enumerator);
                return enumerator.Current;
            }
        }

        // Gets the key of the current dictionary entry.
        object IDictionaryEnumerator.Key
        {
            get
            {
                IEnumerator enumerator =
                    ((IEnumerator) this);
                return enumerator.Current.Key;
            }
        }

        // Gets the value of the current dictionary entry.
        object IDictionaryEnumerator.Value
        {
            get
            {
                IEnumerator enumerator =
                    ((IEnumerator) this);
                return enumerator.Current.Value;
            }
        }

        // Gets both the key and the value of the current dictionary entry.
        DictionaryEntry IDictionaryEnumerator.Entry
        {
            get
            {
                IEnumerator enumerator =
                    ((IEnumerator) this);
                return new DictionaryEntry(enumerator.Current.Key,
                    enumerator.Current.Value);
            }
        }

        // Move enumerator to the next entry.
        public bool MoveNext()
        {
            return _enumerator.MoveNext();
        }

        // Reset enumerator to start position.
        public void Reset()
        {
            _enumerator.Reset();
        }

        // Unused dispose pattern.
        public void Dispose()
        {
        }
    }

}

最后一步是实现指定的接口IDictionary和IEnumerable。一些方法和属性是显式实现的,也就是说,它们的使用需要预先转换为适当的接口类型。

public partial class NameValueCollection :
  IDictionary,
  IEnumerable
{
    // Gets an collection containing the values.
    ICollection IDictionary.Keys => Keys;

    // Gets an collection containing the values.
    ICollection IDictionary.Values => Values;

    // Indicates whether the collection is read-only.
    public new bool IsReadOnly => base.IsReadOnly;

    // Indicates whether the collection contains a fixed number of items.
    public bool IsFixedSize => false;

    // Determines whether the collection contains an element with the specified key.
    bool IDictionary.Contains(object key)
    {
        return key is string s && Keys.Contains(s);
    }

    // Adds an object with the specified key to the colletion.
    void IDictionary.Add(object key, object value)
    {
        Add((string)key, (T)value);
    }

    // Removes the element with the specified key from the collection.
    void IDictionary.Remove(object key)
    {
       Remove((string)key);
    }

    // Gets or sets the item with the specified key.
    object IDictionary.this[object key]
    {
        get
        {
            return Get((string)key);
        }
        set
        {
            if (value is IEnumerable collection)
            {
                Set((string)key, (T[])collection.ToArray());
            }
            else
            {
                Set((string)key, (T)value);
            }
        }
    }

    // The three methods below return an enumerator for current collection.
    IEnumerator IEnumerable.GetEnumerator()
    {
        return new Enumerator(this);
    }

    public override IEnumerator GetEnumerator()
    {
        return new Enumerator(this);
    }

    IDictionaryEnumerator IDictionary.GetEnumerator()
    {
        return new Enumerator(this);
    }
}

用法
NameValueCollection collection = new NameValueCollection();
collection.Add("a", 123);
collection.Add("a", 456);      // 123 and 456 will be inserted into the same key.
collection.Add("b", 789);      // 789 will be inserted into another key.

int[] a = collection.Get("a"); // contains 123 and 456.
int[] b = collection.Get("b"); // contains 789.

在本文的最后,我想说的是,上面的代码实现了基本功能。在附件中,您将找到完整的源代码,其中包含文章中未包含的一些附加扩展。

https://www.codeproject.com/Articles/5323395/A-Generic-Form-of-the-NameValueCollection

关注
打赏
1665926880
查看更多评论
立即登录/注册

微信扫码登录

0.0488s