c# 非泛型集合类用到的相关接口
c# 非泛型集合类用到的相关接口
IEnumerable 接口
公开枚举数,该枚举数支持在非泛型集合上进行简单迭代。也就是说实现这个接口就可用foreach来遍历集合中的元素了。
它仅有一个方法
public IEnumerator GetEnumerator( )
{
//返回为这个集合实现的迭代器
}
IEnumerator 接口
支持对非泛型集合的简单迭代。它是所有非泛型枚举数的基接口。枚举数可用于读取集合中的数据,但不能用于修改基础集合。
它主要有两个方法和一个只读的属性组成。
public object Current
{
get { //返回当前元素}
}
public bool MoveNext( )
{
//是否还有下一个元素,若有把位置移到下元素所在的位置
}
public void Reset( )
{
//返回枚举数到最初位置,在此位置时引用Current会发生异常
}
#endregion
只要集合保持不变,枚举数就保持有效。如果对集合进行了更改(如添加、修改或删除元素),则枚举数将失效且不可恢复,并且下一次对 MoveNext 或 Reset 的调用将引发 InvalidOperationException。如果在 MoveNext 和 Current 之间修改集合,那么即使枚举数已经无效,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 接口是键/值对的非通用集合的基接口。有关该接口的泛型版本的信息,请参见 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 接口的简单字典类。
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
}
浙公网安备 33010602011771号