mark

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

c# 非泛型集合类用到的相关接口

c# 非泛型集合类用到的相关接口

IEnumerable 接口 
公开枚举数,该枚举数支持在非泛型集合上进行简单迭代。也就是说实现这个接口就可用foreach来遍历集合中的元素了。
它仅有一个方法

        public IEnumerator GetEnumerator( )
        {
            //返回为这个集合实现的迭代器
        }
IEnumerator 接口 
支持对非泛型集合的简单迭代。它是所有非泛型枚举数的基接口。枚举数可用于读取集合中的数据,但不能用于修改基础集合。
它主要有两个方法和一个只读的属性组成。

        public object Current
        {
            get { //返回当前元素}
        }

        public bool MoveNext( )
        {
            //是否还有下一个元素,若有把位置移到下元素所在的位置
        }

        public void Reset( )
        {
            //返回枚举数到最初位置,在此位置时引用Current会发生异常
        }

        #endregion

只要集合保持不变,枚举数就保持有效。如果对集合进行了更改(如添加、修改或删除元素),则枚举数将失效且不可恢复,并且下一次对 MoveNextReset 的调用将引发 InvalidOperationException。如果在 MoveNextCurrent 之间修改集合,那么即使枚举数已经无效,Current 也将返回它所设置成的元素。

枚举数没有对集合的独占访问权;因此,枚举通过集合在本质上不是一个线程安全的过程。即使一个集合已进行同步,其他线程仍可以修改该集合,这将导致枚举数引发异常。若要在枚举过程中保证线程安全,可以在整个枚举过程中锁定集合,或者捕捉由于其他线程进行的更改而引发的异常。

下面是个使用的例子
using System;
using System.Collections;

public class Person
{
    public Person(string fName, string lName)
    {
        this.firstName = fName;
        this.lastName = lName;
    }

    public string firstName;
    public string lastName;
}

public class People : IEnumerable
{
    private Person[] _people;
    public People(Person[] pArray)
    {
        _people = new Person[pArray.Length];

        for (int i = 0; i < pArray.Length; i++)
        {
            _people[i] = pArray[i];
        }
    }

    public IEnumerator GetEnumerator()
    {
        return new PeopleEnum(_people);
    }
}

public class PeopleEnum : IEnumerator
{
    public Person[] _people;

    // Enumerators are positioned before the first element
    // until the first MoveNext() call.
    int position = -1;

    public PeopleEnum(Person[] list)
    {
        _people = list;
    }

    public bool MoveNext()
    {
        position++;
        return (position < _people.Length);
    }

    public void Reset()
    {
        position = -1;
    }

    public object Current
    {
        get
        {
            try
            {
                return _people[position];
            }
            catch (IndexOutOfRangeException)
            {
                throw new InvalidOperationException();
            }
        }
    }
}

class App
{
    static void Main()
    {
        Person[] peopleArray = new Person[3]
        {
            new Person("John", "Smith"),
            new Person("Jim", "Johnson"),
            new Person("Sue", "Rabon"),
        };

        People peopleList = new People(peopleArray);
        foreach (Person p in peopleList)
            Console.WriteLine(p.firstName + " " + p.lastName);

    }
}

/* This code produces output similar to the following:
 *
 * John Smith
 * Jim Johnson
 * Sue Rabon
 *
 */

ICollection 接口 
定义所有非泛型集合的大小、枚举数和同步方法。
它继承了IEnumerable(public interface ICollection : IEnumerable)
它有三个只读的属性和一个方法组成
        public void CopyTo( Array array, int index )
        {
            //从特定的 Array 索引处开始,将 ICollection 的元素复制到一个 Array 中。
        }

        public int Count
        {
            //获取 ICollection 中包含的元素数。
        }

        public bool IsSynchronized
        {
            //获取一个值,该值指示是否同步对 ICollection 的访问(线程安全)。
        }

        public object SyncRoot
        {
            //获取可用于同步 ICollection 访问的对象。
        }

IDictionary 接口 

表示键/值对的非通用集合。

IDictionary 接口是键/值对的非通用集合的基接口。有关该接口的泛型版本的信息,请参见 System.Collections.Generic.IDictionary

每个元素都是一个存储在 DictionaryEntry 对象中的键/值对。

每一对都必须有唯一的键。实现在是否允许键为 空引用(在 Visual Basic 中为 Nothing) 方面有所不同。此值可以为 空引用(在 Visual Basic 中为 Nothing),并且不必是唯一的。IDictionary 接口允许对所包含的键和值进行枚举,但这并不意味着任何特定的排序顺序。

IDictionary 实现有三种类别:只读、固定大小、可变大小。无法修改只读 IDictionary 对象。固定大小的 IDictionary 对象不允许添加或移除元素,但允许修改现有元素。可变大小的 IDictionary 对象允许添加、移除和修改元素。

C# 语言中的 foreach 语句(在 Visual Basic 中为 for each)需要集合中每个元素的类型。由于 IDictionary 对象的每个元素都是一个键/值对,因此元素类型既不是键的类型,也不是值的类型。而是 DictionaryEntry 类型。
 public void Add( object key, object value )
        {
           //在 IDictionary 对象中添加一个带有所提供的键和值的元素。
        }

        public void Clear( )
        {
            //从 IDictionary 对象中移除所有元素。
        }

        public bool Contains( object key )
        {
           // 确定 IDictionary 对象是否包含具有指定键的元素。
        }

        public IDictionaryEnumerator GetEnumerator( )
        {
           //返回一个用于 IDictionary 对象的 IDictionaryEnumerator 对象。
        }

        public bool IsFixedSize
        {
            //获取一个值,该值指示 IDictionary 对象是否具有固定大小
        }

        public bool IsReadOnly
        {
            //获取一个值,该值指示 IDictionary 对象是否为只读。
        }

        public ICollection Keys
        {
            //获取 ICollection 对象,它包含 IDictionary 对象的键
        }

        public void Remove( object key )
        {
            //从 IDictionary 对象中移除带有指定键的元素。
        }

        public ICollection Values
        {
            //获取 ICollection 对象,它包含 IDictionary 对象中的值。
        }

        public object this [object key]
        {
           //获取或设置具有指定键的元素
        }

下面的代码示例演示如何定义实现 IDictionary 接口的简单字典类。

// This class implements a simple dictionary using an array of DictionaryEntry objects (key/value pairs).
public class SimpleDictionary : IDictionary
{
    // The array of items
    private DictionaryEntry[] items;
    private Int32 ItemsInUse = 0;

    // Construct the SimpleDictionary with the desired number of items.
    // The number of items cannot change for the life time of this SimpleDictionary.
    public SimpleDictionary(Int32 numItems)
    {
        items = new DictionaryEntry[numItems];
    }


    #region IDictionary Members
    public bool IsReadOnly { get { return false; } }
    public bool Contains(object key)
    {
       Int32 index;
       return TryGetIndexOfKey(key, out index);
    }
    public bool IsFixedSize { get { return false; } }
    public void Remove(object key)
    {
        if (key == null) throw new ArgumentNullException("key");
        // Try to find the key in the DictionaryEntry array
        Int32 index;
        if (TryGetIndexOfKey(key, out index))
        {
            // If the key is found, slide all the items up.
            Array.Copy(items, index + 1, items, index, ItemsInUse - index - 1);
            ItemsInUse--;
        }
        else
        {
            // If the key is not in the dictionary, just return.
        }
    }
    public void Clear() { ItemsInUse = 0; }
    public void Add(object key, object value)
    {
        // Add the new key/value pair even if this key already exists in the dictionary.
        if (ItemsInUse == items.Length)
            throw new InvalidOperationException("The dictionary cannot hold any more items.");
        items[ItemsInUse++] = new DictionaryEntry(key, value);
    }
    public ICollection Keys
    {
        get
        {
            // Return an array where each item is a key.
            Object[] keys = new Object[ItemsInUse];
            for (Int32 n = 0; n < ItemsInUse; n++)
                keys[n] = items[n].Key;
            return keys;
        }
    }
    public ICollection Values
    {
        get
        {
            // Return an array where each item is a value.
            Object[] values = new Object[ItemsInUse];
            for (Int32 n = 0; n < ItemsInUse; n++)
                values[n] = items[n].Value;
            return values;
        }
    }
    public object this[object key]
    {
        get
        {  
            // If this key is in the dictionary, return its value.
            Int32 index;
            if (TryGetIndexOfKey(key, out index))
            {
                // The key was found; return its value.
                return items[index].Value;
            }
            else
            {
                // The key was not found; return null.
                return null;
            }
        }

        set
        {
            // If this key is in the dictionary, change its value.
            Int32 index;
            if (TryGetIndexOfKey(key, out index))
            {
                // The key was found; change its value.
                items[index].Value = value;
            }
            else
            {
                // This key is not in the dictionary; add this key/value pair.
                Add(key, value);
            }
        }
    }
    private Boolean TryGetIndexOfKey(Object key, out Int32 index)
    {
        for (index = 0; index < ItemsInUse; index++)
        {
            // If the key is found, return true (the index is also returned).
            if (items[index].Key.Equals(key)) return true;
        }
     
        // Key not found, return false (index should be ignored by the caller).
        return false;
    }
    private class SimpleDictionaryEnumerator : IDictionaryEnumerator
    {
        // A copy of the SimpleDictionary object's key/value pairs.
        DictionaryEntry[] items;
        Int32 index = -1;

        public SimpleDictionaryEnumerator(SimpleDictionary sd)
        {
            // Make a copy of the dictionary entries currently in the SimpleDictionary object.
            items = new DictionaryEntry[sd.Count];
            Array.Copy(sd.items, 0, items, 0, sd.Count);
        }

        // Return the current item.
        public Object Current { get { ValidateIndex(); return items[index]; } }

        // Return the current dictionary entry.
        public DictionaryEntry Entry
        {
            get { return (DictionaryEntry) Current; }
        }

        // Return the key of the current item.
        public Object Key { get { ValidateIndex();  return items[index].Key; } }

        // Return the value of the current item.
        public Object Value { get { ValidateIndex();  return items[index].Value; } }

        // Advance to the next item.
        public Boolean MoveNext()
        {
            if (index < items.Length - 1) { index++; return true; }
            return false;
        }

        // Validate the enumeration index and throw an exception if the index is out of range.
        private void ValidateIndex()
        {
            if (index < 0 || index >= items.Length)
            throw new InvalidOperationException("Enumerator is before or after the collection.");
        }

        // Reset the index to restart the enumeration.
        public void Reset()
        {
            index = -1;
        }
    }
    public IDictionaryEnumerator GetEnumerator()
    {
        // Construct and return an enumerator.
        return new SimpleDictionaryEnumerator(this);
    }
    #endregion

    #region ICollection Members
    public bool IsSynchronized { get { return false; } }
    public object SyncRoot { get { throw new NotImplementedException(); } }
    public int Count { get { return ItemsInUse; } }
    public void CopyTo(Array array, int index) { throw new NotImplementedException(); }
    #endregion

    #region IEnumerable Members
    IEnumerator IEnumerable.GetEnumerator()
    {
        // Construct and return an enumerator.
        return ((IDictionary)this).GetEnumerator();
    }
    #endregion
}
posted on 2007-06-14 15:22  一切皆有可能  阅读(606)  评论(1)    收藏  举报