VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > Objective-C编程 >
  • 构建反转排序的泛型字典类6—实现Dictionary接口中的keys和values属性

制作者:剑锋冷月 单位:无忧统计网,www.51stat.net
  完整代码下载:http://file.ddvip.com/2008_10/1224750068_ddvip_5023.rar
  6. 实现IDictionary接口中的Keys和Values属性
  现在我们可以着眼于IDictionary接口的实现。第4节中,专门针对这个接口做了一个最简化的例子,我们来回顾一下,它是怎么实现IDictionary接口中的Keys和Values属性的。
public ICollection Keys
  {  //返回所有键的集合
    get
    {  //把所有键的集合拷贝到新数组中并返回
      Object[] keys = new Object[ItemsInUse];
      for (Int32 n = 0; n < ItemsInUse; n++)
        keys[n] = items[n].Key;
      return keys;
    }
  }
  public ICollection Values
  {  //返回所有值的集合
    get
    {  //把所有值的集合拷贝到新数组中并返回
      Object[] values = new Object[ItemsInUse];
      for (Int32 n = 0; n < ItemsInUse; n++)
        values[n] = items[n].Value;
      return values;
    }
  }
  可以很清楚地看到,它把数组里的所有元素拷贝到另一块内存空间中并返回,这再一次带来了性能问题,如果频繁地访问Keys和Values属性还会给垃圾回收带来压力。最好的解决办法当然是直接引用而不是拷贝数组里的元素,你还希望增加一些功能,可以使用索引访问Keys属性或Values属性所返回的ICollection。但从第5节中的图2(最好直接下载下来以方便观看)中可以看到ICollection接口只有寥寥几个成员,并没有Item属性,怎么办呢?当然是从ICollection的子接口中寻找合适的接口了。我们知道,ICollection接口是集合接口的基接口,而它的子接口则是更专用的集合接口,如IDictionary表示带有键值对的集合,IList表示值的集合,它们都可以按索引访问。
  所以这一次你决定另外实现公有的Keys和Values属性,并返回一个ILst<T>接口,并手动实现它,一方面满足所有的功能,另一方面也可以实现IDictionary和IDictionary<TKey, TValue>接口的Keys和Values属性。好,先来看看ILst<T>接口的关系图:
  
  图4 IList<T>接口关系图
  可以看到,实现它并不简单,好在我们将屏蔽所有对元素进行改动的功能。当然,首先还是要要实现一个枚举器(感觉又回到了第2节:http://cgbluesky.blog.163.com/blog/static/241235582008113103320661/ ),不同的地方在于,这次枚举器跟调用类的关系不再是嵌套关系,它们处于同一层次,都是ReversibleSortedList的嵌套类。另外由于引用外部类集合,这里也不需要考虑反向排序的问题。
  下面是Keys属性枚举时所需要的枚举器:
#region ReversibleSortedListKeyEnumerator
  private sealed class ReversibleSortedListKeyEnumerator :
    IEnumerator<TKey>, IDisposable, IEnumerator
  {
    // 成员变量
    private ReversibleSortedList<TKey, TValue> _ReversibleSortedList;
    private TKey currentKey; //记录当前值
    private int index; //记录当前索引
    private int version; //记录此类创建时,外部类的版本号
    //构造方法
    internal ReversibleSortedListKeyEnumerator(
        ReversibleSortedList<TKey, TValue> ReversibleSortedList)
    {  //传递外部类元素所在集合的引用
      this._ReversibleSortedList = ReversibleSortedList;
      this.version = ReversibleSortedList.version;
    }
    public void Dispose()
    {
      this.index = 0;
      this.currentKey = default(TKey);
    }
    public bool MoveNext()
    {
      if (this.version != this._ReversibleSortedList.version)
      {
        throw new InvalidOperationException(
          "枚举版本检查错误");
      }
      if (this.index < this._ReversibleSortedList.Count)
      {
        this.currentKey = this._ReversibleSortedList.keys[this.index];
        this.index++;
        return true;
      }
      this.index = this._ReversibleSortedList.Count + 1;
      this.currentKey = default(TKey);
      return false;
    }
    void IEnumerator.Reset()
    {
      if (this.version != this._ReversibleSortedList.version)
      {
        throw new InvalidOperationException(
          "枚举版本检查错误");
      }
      this.index = 0;
      this.currentKey = default(TKey);
    }
    // 属性
    public TKey Current
    {
      get
      {
        return this.currentKey;
      }
    }
    object IEnumerator.Current
    {
      get
      {
        if ((this.index == 0) || (this.index ==
            (this._ReversibleSortedList.Count + 1)))
        {
          throw new InvalidOperationException(
              "不能进行枚举操作");
        }
        return this.currentKey;
      }
    }
  }
  #endregion
  同理,Values属性枚举时所需要的枚举器代码类似:
ReversibleSortedListValueEnumerator#region ReversibleSortedListValueEnumerator
  private sealed class ReversibleSortedListValueEnumerator :
    IEnumerator<TValue>, IDisposable, IEnumerator
  {
    // 成员变量
    private ReversibleSortedList<TKey, TValue> _ReversibleSortedList;
    private TValue currentValue;
    private int index;
    private int version;
    internal ReversibleSortedListValueEnumerator(
             ReversibleSortedList<TKey, TValue> ReversibleSortedList)
    {
      this._ReversibleSortedList = ReversibleSortedList;
      this.version = ReversibleSortedList.version;
    }
    public void Dispose()
    {
      this.index = 0;
      this.currentValue = default(TValue);
    }
    public bool MoveNext()
    {
      if (this.version != this._ReversibleSortedList.version)
      {
        throw new InvalidOperationException(
          "Enumeration failed version check");
      }
      if (this.index < this._ReversibleSortedList.Count)
      {
        this.currentValue = this._ReversibleSortedList.values[this.index];
        this.index++;
        return true;
      }
      this.index = this._ReversibleSortedList.Count + 1;
      this.currentValue = default(TValue);
      return false;
    }
    void IEnumerator.Reset()
    {
      if (this.version != this._ReversibleSortedList.version)
      {
        throw new InvalidOperationException(
          "Enumeration failed version check");
      }
      this.index = 0;
      this.currentValue = default(TValue);
    }
    // 属性
    public TValue Current
    {
      get
      {
        return this.currentValue;
      }
    }
    object IEnumerator.Current
    {
      get
      {
        if ((this.index == 0) || (this.index ==
            (this._ReversibleSortedList.Count + 1)))
        {
          throw new InvalidOperationException(
              "Enumeration operation could not occur");
        }
        return this.currentValue;
      }
    }
  }
  #endregion
  枚举器实现了,接下来实现Keys所需要的IList<T>。注意,这里通过弹出异常屏蔽了所有企图对元素进行修改的操作。
KeyListK,V#region KeyList<K,V>
  private sealed class KeyList<K, V> : IList<K>, ICollection<K>,
                        IEnumerable<K>, ICollection, IEnumerable
  {
    // 成员变量
    private ReversibleSortedList<K, V> _dict;
    //成员方法
    internal KeyList(ReversibleSortedList<K, V> dictionary)
    {
      this._dict = dictionary;
    }
    public void Add(K key)
    {
      throw new NotSupportedException("不支持Add操作");
    }
    public void Clear()
    {
      throw new NotSupportedException("不支持Clear操作");
    }
    public bool Contains(K key)
    {
      return this._dict.ContainsKey(key);
    }
    public void CopyTo(K[] array, int arrayIndex)
    {
      Array.Copy(this._dict.keys, 0, array, arrayIndex, this._dict.Count);
    }
    public IEnumerator<K> GetEnumerator()
    {
      return new
         ReversibleSortedList<K, V>.ReversibleSortedListKeyEnumerator(
                           this._dict);
    }
    public int IndexOf(K key)
    {
      if (key == null)
      {
        throw new ArgumentNullException("key");
      }
      int num1 = Array.BinarySearch<K>(this._dict.keys, 0,
                          this._dict.Count, key,
                          this._dict._sortDirectionComparer);
      if (num1 >= 0)
      {
        return num1;
      }
      return -1;
    }
    public void Insert(int index, K value)
    {
      throw new NotSupportedException("不支持Insert操作");
    }
    public bool Remove(K key)
    {
      return false;
    }
    public void RemoveAt(int index)
    {
      throw new NotSupportedException("不支持RemoveAt操作");
    }
    void ICollection.CopyTo(Array array, int arrayIndex)
    {
      if ((array != null) && (array.Rank != 1))
      {
        throw new ArgumentException(
           "不支持多维数组");
      }
      try
      {
        Array.Copy(this._dict.keys, 0, array, arrayIndex,
              this._dict.Count);
      }
      catch (ArrayTypeMismatchException atme)
      {
        throw new ArgumentException("错误的数组类型", atme);
      }
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
      return new
          ReversibleSortedList<K, V>.ReversibleSortedListKeyEnumerator(
            this._dict);
    }
    // 属性
    public int Count
    {
      get
      {
        return this._dict._size;
      }
    }
    public bool IsReadOnly
    {
      get
      {
        return true;
      }
    }
    public K this[int index]
    {
      get
      {
        return this._dict.GetKey(index);
      }
      set
      {
        throw new NotSupportedException("不支持通过索引进行更改的操作");
      }
    }
    bool ICollection.IsSynchronized
    {
      get
      {
        return false;
      }
    }
    object ICollection.SyncRoot
    {
      get
      {
        return this._dict;
      }
    }
  }
  #endregion
  同理,Values所需要的Llist<T>代码相似:
ValueList K, V definition#region ValueList <K, V> definition
  private sealed class ValueList<K, V> : IList<V>, ICollection<V>,
    IEnumerable<V>, ICollection, IEnumerable
  {
    // 成员变量
    private ReversibleSortedList<K, V> _dict;
    // 成员方法
    internal ValueList(ReversibleSortedList<K, V> dictionary)
    {
      this._dict = dictionary;
    }
    public void Add(V key)
    {
      throw new NotSupportedException("不支持Add操作");
    }
    public void Clear()
    {
      throw new NotSupportedException("不支持Clear操作");
    }
    public bool Contains(V value)
    {
      return this._dict.ContainsValue(value);
    }
    public void CopyTo(V[] array, int arrayIndex)
    {
      Array.Copy(this._dict.values, 0, array, arrayIndex, this._dict.Count);
    }
    public IEnumerator<V> GetEnumerator()
    {
      return new
          ReversibleSortedList<K, V>.ReversibleSortedListValueEnumerator(
          this._dict);
    }
    public int IndexOf(V value)
    {
      return Array.IndexOf<V>(this._dict.values, value, 0, this._dict.Count);
    }
    public void Insert(int index, V value)
    {
      throw new NotSupportedException("不支持Insert操作");
    }
    public bool Remove(V value)
    {
      return false;
    }
    public void RemoveAt(int index)
    {
      throw new NotSupportedException("不支持RemoveAt操作");
    }
    void ICollection.CopyTo(Array array, int arrayIndex)
    {
      if ((array != null) && (array.Rank != 1))
      {
        throw new ArgumentException(
          "不支持多维数组");
      }
      try
      {
        Array.Copy(this._dict.values, 0, array, arrayIndex,
              this._dict.Count);
      }
      catch (ArrayTypeMismatchException atme)
      {
        throw new ArgumentException("错误的数组类型", atme);
      }
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
      return new
          ReversibleSortedList<K, V>.ReversibleSortedListValueEnumerator(
          this._dict);
    }
    // 属性
    public int Count
    {
      get
      {
        return this._dict._size;
      }
    }
    public bool IsReadOnly
    {
      get
      {
        return true;
      }
    }
    public V this[int index]
    {
      get
      {
        return this._dict.GetByIndex(index);
      }
      set
      {
        throw new NotSupportedException("不支持通过索引改变元素值");
      }
    }
    bool ICollection.IsSynchronized
    {
      get
      {
        return false;
      }
    }
    object ICollection.SyncRoot
    {
      get
      {
        return this._dict;
      }
    }
  }
  #endregion
  上面两个IList<T>接口代码调用了外部类的一些方法,需要把它们添加到ReversibleSortedList类中:
  公有方法如下:
//查找指定键索引
  public int IndexOfKey(TKey key)
  {
    if (key.Equals(null))
    {
      throw new ArgumentNullException("key");
    }
    int num1 = Array.BinarySearch<TKey>(this.keys, 0, this._size, key,
                        this._sortDirectionComparer);
    if (num1 < 0)
    {
      return -1;
    }
    return num1;
  }
  //查找指定值索引
  public int IndexOfValue(TValue value)
  {
    return Array.IndexOf<TValue>(this.values, value, 0, this._size);
  }
  //判断是否包含指定键
  public bool ContainsKey(TKey key)
  {
    return (this.IndexOfKey(key) >= 0);
  }
  //判断是否包含指定值
  public bool ContainsValue(TValue value)
  {
    return (this.IndexOfValue(value) >= 0);
  }
  私有方法如下:
  private TValue GetByIndex(int index)
  {
    if ((index < 0) || (index >= this._size))
    {
      throw new ArgumentOutOfRangeException("index", "Index out of range");
    }
    return this.values[index];
  }
  //返回指定索引的键
  private TKey GetKey(int index)
  {
    if ((index < 0) || (index >= this._size))
    {
      throw new ArgumentOutOfRangeException("index", "Index out of range");
    }
    return this.keys[index];
  }
  private void Insert(int index, TKey key, TValue value)
  {  //在指定索引入插入数据
    if (this._size == this.keys.Length)
    {
      this.EnsureCapacity(this._size + 1);
    }
    if (index < this._size)
    {  //当插入元素不是添加在未尾时,移动插入点后面的元素
      Array.Copy(this.keys, index, this.keys, (int)(index + 1),
            (int)(this._size - index));
      Array.Copy(this.values, index, this.values, (int)(index + 1),
            (int)(this._size - index));
    }
    this.keys[index] = key; //在插入点插入键
    this.values[index] = value; //在插入点插入值
    this._size++;
    this.version++;
  }
  private KeyList<TKey, TValue> GetKeyListHelper()
  {  //获取键的IList<T>集合
    if (this.keyList == null)
    {
      this.keyList = new KeyList<TKey, TValue>(this);
    }
    return this.keyList;
  }
  private ValueList<TKey, TValue> GetValueListHelper()
  {  //获取值的IList<T>集合
    if (this.valueList == null)
    {
      this.valueList = new ValueList<TKey, TValue>(this);
    }
    return this.valueList;
  }
  写了这么多代码,终于可以实现Keys和Values属性了。
  首先添加这两个属性所需的成员变量:
  private KeyList<TKey, TValue> keyList;
  private ValueList<TKey, TValue> valueList;
  然后实现Keys和Values属性,以上这么多代码,就是为了这两个属性:
  public IList<TKey> Keys
  {
    get
    {
      return this.GetKeyListHelper();
    }
  }
  public IList<TValue> Values
  {
    get
    {
      return this.GetValueListHelper();
    }
  }
  看到这,你是不是有些不耐烦了,反正我是有这样的感觉了。但有一点你必须明白,FCL里的代码就是这么实现的。
  好,做了这么多工作,终于可以看看成果,测试一下是否可用了。在Main方法添加如下代码:
  static void Main()
  {
    ReversibleSortedList<int, string> rs = new ReversibleSortedList<int, string>();
    //添加元素
    rs.Add(3, "a");
    rs.Add(1, "b");
    rs.Add(2, "c");
    rs.Add(6, "d");
    rs.Add(5, "e");
    rs.Add(4, "f");
    //打印键/值
    foreach (KeyValuePair<int, string> d in rs)
    {
      Console.WriteLine(d.Key + "  " + d.Value);
    }
    //打印键,这里访问了Keys属性
    foreach (int i in rs.Keys)
    {
      Console.Write(i + " ");
    }
    Console.WriteLine();//换行
    //打印值,这里访问了Values属性
    foreach (string s in rs.Values)
    {
      Console.Write(s + " ");
    }
    Console.WriteLine();//换行
    Console.WriteLine(rs.Keys[3]); //通过索引访问键
    Console.WriteLine(rs.Values[4]); //通过索引访问值
  }
  上帝啊!太痛苦了,如果你也有这样的感觉,请下载现成的代码,更改Main()方法里的东西,尝试是否能通过Keys和Values属性更改元素。
  ReversibleSortedList 0.5版本:实现Keys和Values属性
  运行结果:
1  b
2  c
3  a
4  f
5  e
6  d
1 2 3 4 5 6
b c a f e d
4
e
  所以这一次你决定另外实现公有的Keys和Values属性,并返回一个ILst<T>接口,并手动实现它,一方面满足所有的功能,另一方面也可以实现IDictionary和IDictionary<TKey, TValue>接口的Keys和Values属性。好,先来看看ILst<T>接口的关系图:
  
  图4 IList<T>接口关系图
  可以看到,实现它并不简单,好在我们将屏蔽所有对元素进行改动的功能。当然,首先还是要要实现一个枚举器(感觉又回到了第2节:http://cgbluesky.blog.163.com/blog/static/241235582008113103320661/ ),不同的地方在于,这次枚举器跟调用类的关系不再是嵌套关系,它们处于同一层次,都是ReversibleSortedList的嵌套类。另外由于引用外部类集合,这里也不需要考虑反向排序的问题。
  下面是Keys属性枚举时所需要的枚举器:
#region ReversibleSortedListKeyEnumerator
  private sealed class ReversibleSortedListKeyEnumerator :
    IEnumerator<TKey>, IDisposable, IEnumerator
  {
    // 成员变量
    private ReversibleSortedList<TKey, TValue> _ReversibleSortedList;
    private TKey currentKey; //记录当前值
    private int index; //记录当前索引
    private int version; //记录此类创建时,外部类的版本号
    //构造方法
    internal ReversibleSortedListKeyEnumerator(
        ReversibleSortedList<TKey, TValue> ReversibleSortedList)
    {  //传递外部类元素所在集合的引用
      this._ReversibleSortedList = ReversibleSortedList;
      this.version = ReversibleSortedList.version;
    }
    public void Dispose()
    {
      this.index = 0;
      this.currentKey = default(TKey);
    }
    public bool MoveNext()
    {
      if (this.version != this._ReversibleSortedList.version)
      {
        throw new InvalidOperationException(
          "枚举版本检查错误");
      }
      if (this.index < this._ReversibleSortedList.Count)
      {
        this.currentKey = this._ReversibleSortedList.keys[this.index];
        this.index++;
        return true;
      }
      this.index = this._ReversibleSortedList.Count + 1;
      this.currentKey = default(TKey);
      return false;
    }
    void IEnumerator.Reset()
    {
      if (this.version != this._ReversibleSortedList.version)
      {
        throw new InvalidOperationException(
          "枚举版本检查错误");
      }
      this.index = 0;
      this.currentKey = default(TKey);
    }
    // 属性
    public TKey Current
    {
      get
      {
        return this.currentKey;
      }
    }
    object IEnumerator.Current
    {
      get
      {
        if ((this.index == 0) || (this.index ==
            (this._ReversibleSortedList.Count + 1)))
        {
          throw new InvalidOperationException(
              "不能进行枚举操作");
        }
        return this.currentKey;
      }
    }
  }
  #endregion
 


相关教程