版权声明:本文为博主原创文章,未经博主允许不得转载。
了解了ICollection接口、迭代以及泛型集合,下面再详细了解一下IList接口。
通过MSDN可以看到IList接口有两种:
元素为object类型的IList接口,可以放不同类型的对象引用;
IList<T>泛型接口,只能存放指定类型的对象引用。
其实,IList和IList<T>也称之为向量,特点是可以动态的改变集合的长度,无需确定集合的初始长度,集合会随着存放数据的数量自动变化。
可以看到IList和IList<T>的继承关系:
- [ComVisibleAttribute(true)]
- public interface IList : ICollection, IEnumerable
- public interface IList<T> : ICollection<T>,
- IEnumerable<T>, IEnumerable
现在再返回去看下,IList和IList<T>的区别,看如下代码,ArrayList是继承IList的,List继承IList<T>:
- public class IListClass
- {
- void test()
- {
- TestClass1 c1 = null;
- ArrayList arryList = new ArrayList();
- arryList.Add(c1);
- List<TestClass1> list = new List<TestClass1>();
- list.Add(c1);
- //取值
- TestClass1 getC1Array = arryList[0] as TestClass1;//必须要一次强制转换
- TestClass1 getC1List = list[0];//不需要转换,所谓泛型
- }
- }
- public class TestClass1
- {
- }
这下就比较明白了。
一、IList接口概述
ILis接口从ICollection接口继承,具备以下特性,
Count属性——获取集合元素个数;
GetEnumerator方法——可以迭代;
CopyTo方法——将指定元素复制到另一个数组中;
Clear方法——清空整个集合。
IList新增特性,
索引器属性——根据索引访问集合中任意元素;
Add方法——向集合末尾添加元素;
Insert方法——向集合指定位置插入元素;
Remove方法——移除指定元素;(包括RemoveAt)
Contains方法——判断对象是否在集合中;
IndexOf方法——查找指定对象在集合中的索引位置。
另外,IList接口集合按照顺序存放元素,不改变元素存放顺序。
2、算法
向量集合和数组一样,具备随即访问的特点。即无论访问向量集合的任何一个单元,所需的访问时间是完全相同的。在向量类中,实际上依然使用普通数组来记录集合数据,向量类使用了一些算法技巧,让整个类对外表现不同于普通数组的重要特点:可以动态改变数组长度。具体算法如下:
在内部数组足够长的情况下,直接进行添加和插入操作,在内部数组长度不足的情况下,按照内部数组长度增加2倍作为新的数组的长度,然后进行数据搬移(即把就数组数组移到新数组中)。向量在分配元素存储空间时,会多分配一些冗余空间,尽量减少内存分配次数。在数据删除时,并不改变内部数组长度,仅仅是使用被删除数据之后的数据覆盖被删除的数据。
不过向量每次分配空间时都多分配一些冗余空间,会造成内存的压力,因此在程序中应该尽量避免集中的次数繁多的内存分配。
三、实现类
IList和IList<T>的实现类,分别是ArrayList类和List<T>类。
ArrayList类处于System.Collection命名空间下;
List<T>类处于System.Collection.Specialized命名空间下。
四、实现代码(非泛型)
- /// <summary>
- /// 实现IList,非泛型
- /// </summary>
- public class ArrayList : IList
- {
- /// <summary>
- /// 迭代
- /// </summary>
- public struct Enumertor : IEnumerator
- {
- /// <summary>
- /// 迭代索引
- /// </summary>
- private int index;
- /// <summary>
- /// 迭代器所属的向量类对象的引用
- /// </summary>
- private ArrayList arrayList;
- /// <summary>
- /// 构造函数
- /// </summary>
- /// <param name="arrayList">迭代器所属的集合类</param>
- public Enumertor(ArrayList arrayList)
- {
- this.arrayList = arrayList;
- this.index = -1;
- }
- /// <summary>
- /// 获取当前对象,根据index的值返回向量对应的对象引用
- /// </summary>
- public object Current
- {
- get
- {
- return arrayList[index];
- }
- }
- /// <summary>
- /// 将迭代器指向下一个数据位置,通过改变index的值,加1或减1
- /// </summary>
- /// <returns></returns>
- public bool MoveNext()
- {
- if (this.index < arrayList.Count)
- {
- ++this.index;
- }
- return this.index < arrayList.Count;
- }
- /// <summary>
- /// 迭代器回到起始位置,将index置为-1
- /// </summary>
- public void Reset()
- {
- this.index = -1;
- }
- }
- /// <summary>
- /// 保存集合的数组
- /// </summary>
- private object[] array = new object[1];
- /// <summary>
- /// 当前集合的长度
- /// </summary>
- private int count;
- /// <summary>
- /// 默认构造函数
- /// </summary>
- public ArrayList()
- {
- }
- /// <summary>
- /// 参数构造函数,通过参数指定内部数组长度,减少重新分配空间
- /// </summary>
- /// <param name="capacity"></param>
- public ArrayList(int capacity)
- {
- if (capacity < 0)
- {
- throw new Exception();
- }
- if (capacity == 0)
- {
- capacity = 1;
- }
- this.array = new object[capacity];
- this.count = 0;
- }
- public int Count
- {
- get
- {
- return this.count;//该属性只读
- }
- }
- /// <summary>
- /// 集合实际使用长度
- /// </summary>
- public int Capacity
- {
- get
- {
- return this.array.Length;
- }
- }
- /// <summary>
- /// 是否固定大小
- /// </summary>
- public bool IsFixedSize
- {
- get
- {
- return false;
- }
- }
- /// <summary>
- /// 是否只读集合
- /// </summary>
- public bool IsReadOnly
- {
- get
- {
- return false;
- }
- }
- /// <summary>
- /// 是否同步,即是否支持多线程访问
- /// </summary>
- public bool IsSynchronized
- {
- get
- {
- return false;
- }
- }
- /// <summary>
- /// 同步对象
- /// </summary>
- public object SyncRoot
- {
- get
- {
- return null;
- }
- }
- /// <summary>
- /// 当array长度不足时,重新分配新的长度足够的数组
- /// </summary>
- /// <returns></returns>
- private object[] GetNewArray()
- {
- return new object[(this.array.Length + 1) * 2];
- }
- public int Add(object value)
- {
- int newCount = this.count + 1;
- if (this.array.Length < newCount)//长度不足
- {
- object[] newArray = GetNewArray();
- Array.Copy(this.array, newArray, this.count);
- this.array = newArray;//重新引用,指向新数组
- }
- //增加新元素
- this.array[this.count] = value;
- this.count = newCount;
- //返回新元素的索引位置
- return this.count - 1;
- }
- /// <summary>
- /// 索引器属性,按索引返回向量中的某一项
- /// </summary>
- /// <param name="index"></param>
- /// <returns></returns>
- public object this[int index]
- {
- get
- {
- if (index < 0 || index >= this.count)
- {
- throw new Exception();
- }
- return this.array[index];
- }
- set
- {
- if (index < 0 || index >= this.count)
- {
- throw new Exception();
- }
- this.array[index] = value;
- }
- }
- /// <summary>
- /// 删除集合中的元素
- /// </summary>
- /// <param name="index"></param>
- /// <param name="count"></param>
- public void RemoveRange(int index, int count)
- {
- if (index < 0)
- {
- throw new Exception();
- }
- int removeIndex = index + count;//计算集合中最后一个被删元素的索引
- if (count < 0 || removeIndex > this.count)
- {
- throw new Exception();
- }
- //删除其实是将要删除元素之后的所有元素拷贝到要删除元素的位置覆盖掉
- Array.Copy(this.array, index + 1, this.array, index + count - 1, this.count - removeIndex);
- //重新设置集合长度
- this.count -= count;
- }
- /// <summary>
- /// 查找对应的数组项,实际是遍历查找
- /// </summary>
- /// <param name="value"></param>
- /// <returns></returns>
- public int IndexOf(object value)
- {
- int index = 0;
- if (value == null)
- {
- while (index < this.count)
- {
- if (this.array[index] == null)
- {
- return index;
- }
- ++index;
- }
- }
- else
- {
- while (index < this.count)
- {
- if (this.array[index].Equals(value))
- {
- return index;
- }
- ++index;
- }
- }
- return -1;
- }
- /// <summary>
- /// 从集合中删除指定元素
- /// </summary>
- /// <param name="value"></param>
- public void Remove(object value)
- {
- int index = this.IndexOf(value);
- if (index >= 0)
- {
- this.RemoveRange(index, 1);
- }
- }
- /// <summary>
- /// 从集合中删除指定位置的元素
- /// </summary>
- /// <param name="index"></param>
- public void RemoveAt(int index)
- {
- RemoveRange(index, 1);
- }
- /// <summary>
- /// 获取最后一个元素的引用后删除最后一个元素
- /// </summary>
- /// <returns></returns>
- public object PopBack()
- {
- object obj = this.array[this.count - 1];
- RemoveAt(this.count - 1);
- return obj;
- }
- /// <summary>
- /// 获取第一个元素引用并删除第一个元素
- /// </summary>
- /// <returns></returns>
- public object PropFront()
- {
- object obj = this.array[0];
- RemoveAt(0);
- return obj;
- }
- /// <summary>
- /// 插入元素
- /// </summary>
- /// <param name="index"></param>
- /// <param name="value"></param>
- public void Insert(int index, object value)
- {
- if (index >= this.count)
- {
- throw new Exception();
- }
- //插入元素当空间不足时也是声明新的2倍长度数组,并拷贝旧数据。
- //插入数据原理是,将指定位置后的数据全部后移,再将新数据放在指定位置。
- int newCount = this.count + 1;
- if (this.array.Length < newCount)
- {
- object[] newArray = GetNewArray();
- Array.Copy(this.array, newArray, index);
- this.array = newArray;
- }
- Array.Copy(this.array, index, this.array, index + 1, this.count - index);
- this.array[index] = value;
- this.count = newCount;
- }
- /// <summary>
- /// 查看当前集合是否包含指定对象
- /// </summary>
- /// <param name="value"></param>
- /// <returns></returns>
- public bool Contains(object value)
- {
- return this.IndexOf(value) >= 0;
- }
- /// <summary>
- /// 将集合的长度改变为实际长度
- /// </summary>
- public void TrimToSize()
- {
- //为了消除Add和Insert时增加的冗余,原理是新生成一个和实际长度相同的数组,然后将值全部移过来。
- if (this.array.Length > this.count)
- {
- object[] newArray = null;
- if (this.count > 0)
- {
- newArray = new object[this.count];
- Array.Copy(this.array, newArray, this.count);
- }
- else
- {
- newArray = new object[1];
- }
- this.array = newArray;
- }
- }
- /// <summary>
- /// 清空集合
- /// </summary>
- public void Clear()
- {
- this.count = 0;
- }
- /// <summary>
- /// 获取集合的迭代器
- /// </summary>
- /// <returns></returns>
- public IEnumerator GetEnumerator()
- {
- Enumertor enumerator = new Enumertor(this);
- return enumerator;
- }
- /// <summary>
- /// 转移集合元素
- /// </summary>
- /// <param name="targetArray"></param>
- /// <param name="index"></param>
- public void CopyTo(Array targetArray, int index)
- {
- Array.Copy(this.array, 0, targetArray, index, this.count);
- }
- }
调用测试:
- static void Main(string[] args)
- {
- //调用测试
- ArrayList myArrayList = new ArrayList();
- myArrayList.Add(40);
- myArrayList.Add(80);
- myArrayList.Add("Hello");
- //使用for循环遍历
- for (int i = 0; i < myArrayList.Count; i++)
- {
- Console.WriteLine(myArrayList[i]);
- }
- Console.WriteLine("---------------------");
- //使用迭代循环
- foreach (object obj in myArrayList)
- {
- Console.WriteLine(obj);
- }
- Console.WriteLine("---------------------");
- myArrayList.Insert(1, "Insert");
- foreach (object obj in myArrayList)
- {
- Console.WriteLine(obj);
- }
- Console.WriteLine("---------------------");
- myArrayList.Remove("Insert");
- foreach (object obj in myArrayList)
- {
- Console.WriteLine(obj);
- }
- Console.WriteLine("---------------------");
- myArrayList.RemoveAt(1);
- foreach (object obj in myArrayList)
- {
- Console.WriteLine(obj);
- }
- Console.WriteLine("---------------------");
- myArrayList.Clear();
- foreach (object obj in myArrayList)
- {
- Console.WriteLine(obj);
- }
- Console.WriteLine("---------------------");
- Random rand = new Random();
- for (int i = 0; i < 10; i++)
- {
- myArrayList.Add(rand.Next(10));
- }
- foreach (object obj in myArrayList)
- {
- Console.WriteLine(obj);
- }
- Console.WriteLine("---------------------");
- Console.WriteLine("集合是否包含为1的元素 ? " + (myArrayList.Contains(0) ? "包含" : "不包含"));
- Console.WriteLine("元素1的位置 " + myArrayList.IndexOf(1));
- Console.ReadLine();
- }
结果:
代码下载:http://download.csdn.net/detail/yysyangyangyangshan/4686479
版权声明:本文为博主原创文章,未经博主允许不得转载。
了解了ICollection接口、迭代以及泛型集合,下面再详细了解一下IList接口。
通过MSDN可以看到IList接口有两种:
元素为object类型的IList接口,可以放不同类型的对象引用;
IList<T>泛型接口,只能存放指定类型的对象引用。
其实,IList和IList<T>也称之为向量,特点是可以动态的改变集合的长度,无需确定集合的初始长度,集合会随着存放数据的数量自动变化。
可以看到IList和IList<T>的继承关系:
现在再返回去看下,IList和IList<T>的区别,看如下代码,ArrayList是继承IList的,List继承IList<T>:
这下就比较明白了。
一、IList接口概述
ILis接口从ICollection接口继承,具备以下特性,
Count属性——获取集合元素个数;
GetEnumerator方法——可以迭代;
CopyTo方法——将指定元素复制到另一个数组中;
Clear方法——清空整个集合。
IList新增特性,
索引器属性——根据索引访问集合中任意元素;
Add方法——向集合末尾添加元素;
Insert方法——向集合指定位置插入元素;
Remove方法——移除指定元素;(包括RemoveAt)
Contains方法——判断对象是否在集合中;
IndexOf方法——查找指定对象在集合中的索引位置。
另外,IList接口集合按照顺序存放元素,不改变元素存放顺序。
2、算法
向量集合和数组一样,具备随即访问的特点。即无论访问向量集合的任何一个单元,所需的访问时间是完全相同的。在向量类中,实际上依然使用普通数组来记录集合数据,向量类使用了一些算法技巧,让整个类对外表现不同于普通数组的重要特点:可以动态改变数组长度。具体算法如下:
在内部数组足够长的情况下,直接进行添加和插入操作,在内部数组长度不足的情况下,按照内部数组长度增加2倍作为新的数组的长度,然后进行数据搬移(即把就数组数组移到新数组中)。向量在分配元素存储空间时,会多分配一些冗余空间,尽量减少内存分配次数。在数据删除时,并不改变内部数组长度,仅仅是使用被删除数据之后的数据覆盖被删除的数据。
不过向量每次分配空间时都多分配一些冗余空间,会造成内存的压力,因此在程序中应该尽量避免集中的次数繁多的内存分配。
三、实现类
IList和IList<T>的实现类,分别是ArrayList类和List<T>类。
ArrayList类处于System.Collection命名空间下;
List<T>类处于System.Collection.Specialized命名空间下。
四、实现代码(非泛型)
调用测试:
结果:
代码下载:http://download.csdn.net/detail/yysyangyangyangshan/4686479