在前面我们知道在C#中有一个List类,可以存储长度不限的数据。列表是使用了泛型来创建的,那我们可以通过泛型来创建自己的一个列表,这样我们能够对泛型和列表有个更深刻的了解。
首先,我们知道列表其实就是一个数组,只不过构造的时候不需要指定长度,那么我们首先要定义一个泛型数组和其中元素个数的变量。
class MyList<T> where T:IComparable
{
private T[] array; //定义一个泛型数组
private int count; //元素个数
}
有了MyList这个类之后,我们要去定义他的构造函数,数组长度可填可不填。
//构造有参数组
public MyList(int size)
{
if (size >= 0)
{
array = new T[size];
}
}
//构造无参数组
public MyList()
{
array = new T[0];
}
这样我们的列表就可以通过构造函数构造出来了,那么列表的基本属性是什么呢?我们要能够获取这个列表的容量大小和元素个数。因为容量大小和元素个数我们只需要获取它的数值,所以不用设置set方法。
//获取容量大小
public int Capacity
{
get { return array.Length; }
}
//获取数组内元素个数
public int Count
{
get { return count; }
}
现在这个列表的构造函数和属性都已经写好了,那么接下来我们需要写这个列表的功能。功能如下
1.Add()方法添加元素
//添加元素
public void Add(T item)
{
//首先判断数组元素是否已满
if (Capacity == Count)
{
//再判断数组是否为空
if (Capacity == 0)
{
array = new T[4];
}
else
{
//不为空的话数组长度增加为原来的两倍
var newArray = new T[Capacity * 2];
Array.Copy(array, newArray, count);
array = newArray;
}
}
array[Count] = item;
count++;
}
2.获取列表的值(为了更方便地访问列表,我们可以使用索引器访问元素)
//获取列表的值
public T GetItem(int index)
{
if (index >= 0 && index <= count - 1)
{
return array[index];
}
else
{
throw new Exception("索引超出范围");
}
}
//通过索引访问元素
public T this[int index] //从源码所获取的方法
{
get { return GetItem(index); }
set
{
if (index >= 0 && index <= count - 1)
{
array[index] = value;
}
else
{
throw new Exception("索引超出范围");
}
}
}
3.插入元素
public void Insert(int index, T item)
{
if (index >= 0 && index <= count - 1)
{
//首先判断数组是否已满
if (Capacity == Count)
{
//再判断数组是否为空
if (Capacity == 0)
{
array = new T[4];
}
else
{
//不为空的话数组长度增加为原来的两倍
var newArray = new T[Capacity * 2];
Array.Copy(array, newArray, count);
array = newArray;
}
}
else
{
for (int i = count - 1; i >= index; i--)
{
array[i + 1] = array[i];
}
array[index] = item;
count++; //插入完之后元素个数自增
}
}
else
{
throw new Exception("索引超出范围");
}
}
4.移除指定位置元素
public void RemoveAt(int index)
{
if (index >= 0 && index <= count - 1)
{
for(int i = index + 1; i <= count - 1; i++)
{
array[i - 1] = array[i]; //将后一个元素的值赋值给前一个元素;
}
count--;
}
else
{
throw new Exception("索引超出范围");
}
}
5.从前往后取得元素在列表中的索引
//从前往后取得元素在列表中的索引
public int IndexOf(T item)
{
for(int i = 0; i <= count - 1; i++)
{
//if(array[i] == item) 因为泛型不能做比较,所以使用equals方法
if(array[i].Equals(item))
{
return i;
}
}
return -1;
}
6.从后往前取得元素在列表中的索引
//从后往前取得元素在列表中的索引
public int LastIndexOf(T item)
{
for(int i = count - 1; i >= 0; i--)
{
if (array[i].Equals(item))
{
return i;
}
}
return -1;
}
7.对列表中的元素进行排序(冒泡排序)
public void Sort()
{
for(int i = 0; i < count - 1; i++)
{
for(int j = 0; j < count - 1 - i; j++) //减去一个i是不遍历已经排序过的元素,提高效率
{
//if (array[i] < array[i + 1]) 因为泛型无法比较大小,所以让泛型使用Compare接口
if (array[j].CompareTo(array[j + 1]) > 0)
{
var temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
}
在这些功能里,有些地方值得注意一下
- 使用泛型声明的元素,当判断是否相等的时候,不能使用”==”来判断,只能使用Equals()方法来判断是否相等。
- 使用泛型声明的元素,当判断两者的大小时,不能使用”>”或”<”来判断,我们需要在类名后面加上”where T:ICompareble”,给泛型继承ICompareble接口,然后使用CompareTo()方法,当比较完的值>0时,说明前面那个数比后面的数大,<0时说明前面的数比后面的数小。
下面贴出源代码
class MyList<T> where T:IComparable
{
private T[] array; //定义一个泛型数组
private int count; //元素个数
//构造有参数组
public MyList(int size)
{
if (size >= 0)
{
array = new T[size];
}
}
//构造无参数组
public MyList()
{
array = new T[0];
}
//获取容量大小
public int Capacity
{
get { return array.Length; }
}
//获取数组内元素个数
public int Count
{
get { return count; }
}
//添加元素
public void Add(T item)
{
//首先判断数组元素是否已满
if (Capacity == Count)
{
//再判断数组是否为空
if (Capacity == 0)
{
array = new T[4];
}
else
{
//不为空的话数组长度增加为原来的两倍
var newArray = new T[Capacity * 2];
Array.Copy(array, newArray, count);
array = newArray;
}
}
array[Count] = item;
count++;
}
//获取列表的值
public T GetItem(int index)
{
if (index >= 0 && index <= count - 1)
{
return array[index];
}
else
{
throw new Exception("索引超出范围");
}
}
//通过索引访问元素
public T this[int index] //从源码所获取的方法
{
get { return GetItem(index); }
set
{
if (index >= 0 && index <= count - 1)
{
array[index] = value;
}
else
{
throw new Exception("索引超出范围");
}
}
}
//插入元素
public void Insert(int index, T item)
{
if (index >= 0 && index <= count - 1)
{
//首先判断数组是否已满
if (Capacity == Count)
{
//再判断数组是否为空
if (Capacity == 0)
{
array = new T[4];
}
else
{
//不为空的话数组长度增加为原来的两倍
var newArray = new T[Capacity * 2];
Array.Copy(array, newArray, count);
array = newArray;
}
}
else
{
for (int i = count - 1; i >= index; i--)
{
array[i + 1] = array[i];
}
array[index] = item;
count++; //插入完之后元素个数自增
}
}
else
{
throw new Exception("索引超出范围");
}
}
//移除指定位置元素
public void RemoveAt(int index)
{
if (index >= 0 && index <= count - 1)
{
for(int i = index + 1; i <= count - 1; i++)
{
array[i - 1] = array[i]; //将后一个元素的值赋值给前一个元素;
}
count--;
}
else
{
throw new Exception("索引超出范围");
}
}
//从前往后取得元素在列表中的索引
public int IndexOf(T item)
{
for(int i = 0; i <= count - 1; i++)
{
//if(array[i] == item) 因为泛型不能做比较,所以使用equals方法
if(array[i].Equals(item))
{
return i;
}
}
return -1;
}
//从后往前取得元素在列表中的索引
public int LastIndexOf(T item)
{
for(int i = count - 1; i >= 0; i--)
{
if (array[i].Equals(item))
{
return i;
}
}
return -1;
}
//对列表中的元素进行排序(冒泡排序)
public void Sort()
{
for(int i = 0; i < count - 1; i++)
{
for(int j = 0; j < count - 1 - i; j++) //减去一个i是不遍历已经排序过的元素,提高效率
{
//if (array[i] < array[i + 1]) 因为泛型无法比较大小,所以让泛型使用Compare接口
if (array[j].CompareTo(array[j + 1]) > 0)
{
var temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
}
}
//主函数
class Program
{
static void Main(string[] args)
{
MyList<int> myList = new MyList<int>();
myList.Add(128);
myList.Add(27);
myList.Add(94);
myList.Add(18);
myList.Add(349);
myList.Add(83);
myList.Add(837);
myList.Add(250);
myList.Add(430);
myList.Add(678);
myList.Insert(0, 1000);
myList.RemoveAt(8);
for(int i = 0; i < myList.Count; i++)
{
Console.Write(myList[i] + " ");
}
Console.WriteLine();
Console.WriteLine(myList.IndexOf(83));
Console.WriteLine(myList.LastIndexOf(18));
Console.WriteLine();
myList.Sort();
for (int i = 0; i < myList.Count; i++)
{
Console.Write(myList[i] + " ");
}
Console.ReadKey();
}
}