c#的IList,IEnumerable和IEnumerator
IList 是 ICollection 接口的子代,并且是所有非泛型列表的基接口。IList 实现有三种类别:只读、固定大小和可变大小。无法修改只读 IList。固定大小的 IList 不允许添加或移除元素,但允许修改现有元素。可变大小的 IList 允许添加、移除和修改元素。
下面的示例演示创建一个简单列表——固定大小列表的 IList 接口的实现。
代码
class SimpleList : IList
{
private object[] _contents = new object[8];
private int _count;
public SimpleList()
{
_count = 0;
}
// IList Members
public int Add(object value)
{
if (_count < _contents.Length)
{
_contents[_count] = value;
_count++;
return (_count - 1);
}
else
{
return -1;
}
}
public void Clear()
{
_count = 0;
}
public bool Contains(object value)
{
bool inList = false;
for (int i = 0; i < Count; i++)
{
if (_contents[i] == value)
{
inList = true;
break;
}
}
return inList;
}
public int IndexOf(object value)
{
int itemIndex = -1;
for (int i = 0; i < Count; i++)
{
if (_contents[i] == value)
{
itemIndex = i;
break;
}
}
return itemIndex;
}
public void Insert(int index, object value)
{
if ((_count + 1 <= _contents.Length) && (index < Count) && (index >= 0))
{
_count++;
for (int i = Count - 1; i > index; i--)
{
_contents[i] = _contents[i - 1];
}
_contents[index] = value;
}
}
public bool IsFixedSize
{
get
{
return true;
}
}
public bool IsReadOnly
{
get
{
return false;
}
}
public void Remove(object value)
{
RemoveAt(IndexOf(value));
}
public void RemoveAt(int index)
{
if ((index >= 0) && (index < Count))
{
for (int i = index; i < Count - 1; i++)
{
_contents[i] = _contents[i + 1];
}
_count--;
}
}
public object this[int index]
{
get
{
return _contents[index];
}
set
{
_contents[index] = value;
}
}
// ICollection Members
public void CopyTo(Array array, int index)
{
int j = index;
for (int i = 0; i < Count; i++)
{
array.SetValue(_contents[i], j);
j++;
}
}
public int Count
{
get
{
return _count;
}
}
public bool IsSynchronized
{
get
{
return false;
}
}
// Return the current instance since the underlying store is not
// publicly available.
public object SyncRoot
{
get
{
return this;
}
}
// IEnumerable Members
public IEnumerator GetEnumerator()
{
// Refer to the IEnumerator documentation for an example of
// implementing an enumerator.
throw new Exception("The method or operation is not implemented.");
}
public void PrintContents(System.Windows.Controls.TextBlock outputBlock)
{
outputBlock.Text += String.Format("List has a capacity of {0} and currently has {1} elements.", _contents.Length, _count) + "\n";
outputBlock.Text += "List contents:";
for (int i = 0; i < Count; i++)
{
outputBlock.Text += String.Format(" {0}", _contents[i]);
}
outputBlock.Text += "\n";
}
}
class SimpleList : IList
{
private object[] _contents = new object[8];
private int _count;
public SimpleList()
{
_count = 0;
}
// IList Members
public int Add(object value)
{
if (_count < _contents.Length)
{
_contents[_count] = value;
_count++;
return (_count - 1);
}
else
{
return -1;
}
}
public void Clear()
{
_count = 0;
}
public bool Contains(object value)
{
bool inList = false;
for (int i = 0; i < Count; i++)
{
if (_contents[i] == value)
{
inList = true;
break;
}
}
return inList;
}
public int IndexOf(object value)
{
int itemIndex = -1;
for (int i = 0; i < Count; i++)
{
if (_contents[i] == value)
{
itemIndex = i;
break;
}
}
return itemIndex;
}
public void Insert(int index, object value)
{
if ((_count + 1 <= _contents.Length) && (index < Count) && (index >= 0))
{
_count++;
for (int i = Count - 1; i > index; i--)
{
_contents[i] = _contents[i - 1];
}
_contents[index] = value;
}
}
public bool IsFixedSize
{
get
{
return true;
}
}
public bool IsReadOnly
{
get
{
return false;
}
}
public void Remove(object value)
{
RemoveAt(IndexOf(value));
}
public void RemoveAt(int index)
{
if ((index >= 0) && (index < Count))
{
for (int i = index; i < Count - 1; i++)
{
_contents[i] = _contents[i + 1];
}
_count--;
}
}
public object this[int index]
{
get
{
return _contents[index];
}
set
{
_contents[index] = value;
}
}
// ICollection Members
public void CopyTo(Array array, int index)
{
int j = index;
for (int i = 0; i < Count; i++)
{
array.SetValue(_contents[i], j);
j++;
}
}
public int Count
{
get
{
return _count;
}
}
public bool IsSynchronized
{
get
{
return false;
}
}
// Return the current instance since the underlying store is not
// publicly available.
public object SyncRoot
{
get
{
return this;
}
}
// IEnumerable Members
public IEnumerator GetEnumerator()
{
// Refer to the IEnumerator documentation for an example of
// implementing an enumerator.
throw new Exception("The method or operation is not implemented.");
}
public void PrintContents(System.Windows.Controls.TextBlock outputBlock)
{
outputBlock.Text += String.Format("List has a capacity of {0} and currently has {1} elements.", _contents.Length, _count) + "\n";
outputBlock.Text += "List contents:";
for (int i = 0; i < Count; i++)
{
outputBlock.Text += String.Format(" {0}", _contents[i]);
}
outputBlock.Text += "\n";
}
}
下面的代码示例演示如何实现自定义集合的 IEnumerable 和 IEnumerator 接口。在此示例中,没有显式调用这些接口的成员,但实现了它们,以便支持使用 foreach循环访问该集合。
代码
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 Example
{
public static void Demo(System.Windows.Controls.TextBlock outputBlock)
{
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)
outputBlock.Text += p.firstName + " " + p.lastName + "\n";
}
}
/* This code produces output similar to the following:
*
* John Smith
* Jim Johnson
* Sue Rabon
*
*/
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 Example
{
public static void Demo(System.Windows.Controls.TextBlock outputBlock)
{
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)
outputBlock.Text += p.firstName + " " + p.lastName + "\n";
}
}
/* This code produces output similar to the following:
*
* John Smith
* Jim Johnson
* Sue Rabon
*
*/