C#List列表及基础方法实现

本片文章主要展现模仿List源码实现自定义List类,对理解C#有一定帮助。

基础内容

Add() 末尾添加元素

Insert() 指定下标插入元素

Count 属性表示元素个数

RemoveAt() 方法指定下标元素删除

IndexOf() 返回第一个元素所在下标

LastIndexOf() 返回最后一个元素所在下标

用泛型数组实现基本List

第一步定义MyList类

class MyList<T>
    {
        private T[] array;//泛型数组用来存储数据,作为类的主体
        private int count = 0;//存储元素个数
        public MyList(int size)
        {
            array = new T[size];
        }
        public MyList()
        {
            array = new T[0];
        }
	}
复制代码

完成类的初始化在此添加两个构造方法,不带参数的构造方法用来新建一个长度为0的数组,带参数的用来构建一个指定长度的数组。

		//获取容量大小
        public int Capacity { get => array.Length; }
        public int Count { get => count; }
复制代码

设置访问器,并且对count字段进行封装,对象可以通过调用Count属性用来获取列表元素个数。
第二部实现Add方法

        public void Add(T item)
        {
            if( Count == Capacity)//是否达到最大容量
            {
                if(Capacity == 0)
                {
                    array = new T[4];
                }
                else
                {
                    EnsureCapacity();
                }
            }
            array[Count] = item;
            count++;
        }

        private void EnsureCapacity()
        {
            //容量不够时,每次扩容一倍
            var newArray = new T[Capacity * 2];
            Array.Copy(array, newArray, Count);
            array = newArray;
        }
复制代码

当向数组中添加元素时出现容量不够,则以当前容量的两倍进行扩容。新建一个两倍长度的数组,然后将原数组成员拷贝到新数组。
添加索引器
希望列表对象能够像数组一样使用[]进行访问,就必须添加索引器。

        //添加索引器
        public T this[int index]
        {
            get { return array[index]; }
            set { array[index] = value; }
        }
复制代码

实现Insert方法
元素的插入方法需要理解一下,首先判断下标越界,其次容量容量足够才进行插入。
将从末尾到index处的元素逐个后移
将item赋值到index处
元素个数加一完成

//插入元素
        public  void Insert(int index,T item)
        {
            if (0 <=index  && index <= Count)
            {
                if (Count == Capacity)
                {
                    //容量不够需要扩容
                    EnsureCapacity();
                }
                //从后往前遍历
                for (int i = Count-1; i >= index; i--)
                {
                    array[i+1] = array[i];
                }
                array[index] = item;
                count++;
            }
            else
            {
                throw new Exception("索引超出范围");
            }
        }
复制代码

实现RemoveAt方法
RemoveAt方法与Insert方法类似。
从index处开始逐个将元素前移
将最后一个元素设为默认值
元素个数减一

//删除指定元素
        public void RemoveAt(int index)
        {
            if (0 <= index && index < Count)
            {
                for (int i = index+1; i < Count; i++)
                {
                    array[i-1] = array[i];
                }
                array[Count - 1] = default(T);
                count--;
            }
            else
            {
                throw new Exception("索引超出范围");
            }
        }
复制代码

实现查找方法
顺序遍历找到第一个相同元素,返回下标。泛型无法使用比较运算符进行比较。使用数组的Equals方法就好。

 //顺序查找第一元素
        public int IndexOf(T item)
        {
            for (int i = 0; i < Count; i++)
            {
                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;
        }
复制代码

实现排序
使用最简的冒泡排序实现
在比较两个泛型元素时,使用CompaerTo方法,必须提供IComparable的泛型约束

class MyList<T> where T:IComparable{}
复制代码
//升序排序
        public void Sort()
        {
            for (int i = 0; i < Count-1; i++)
            {
                for (int j = 0; j < Count-1-i; j++)
                {
                    if (array[j].CompareTo(array[j + 1]) > 0)
                    {
                        T tempItem = array[j];
                        array[j] = array[j + 1];
                        array[j + 1] = tempItem;
                    }
                }
            }
        }
复制代码

实现迭代器
利用yield简化迭代器,只用实现IEnumerable接口就行

class MyList<T>:IEnumerable<T> where T:IComparable{}
复制代码
        public IEnumerator<T> GetEnumerator()
        {
            for (int i = 0; i < Count; i++)
            {
                yield return array[i];
            }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            throw new NotImplementedException();
        }
    }
复制代码

清晰明了,这样便可以forch该列表对象了。

完整代码

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace DotNetStudy
{
    class MyList<T>:IEnumerable<T> where T:IComparable
    {
        private T[] array;

        private int count = 0;

        public MyList(int size)
        {
            array = new T[size];
        }

        public MyList()
        {
            array = new T[0];
        }
        //获取容量大小
        public int Capacity { get => array.Length; }
        public int Count { get => count; }

        public void Add(T item)
        {
            if( Count == Capacity)//是否达到最大容量
            {
                if(Capacity == 0)
                {
                    array = new T[4];
                }
                else
                {
                    EnsureCapacity();
                }
            }
            array[Count] = item;
            count++;
        }

        private void EnsureCapacity()
        {
            //容量不够时,每次扩容一倍
            var newArray = new T[Capacity * 2];
            Array.Copy(array, newArray, Count);
            array = newArray;
        }

        public T GetItem(int index)
        {
            if(index>0 && index < Count)
            {
                return array[index];
            }
            else
            {
                //Console.WriteLine("索引超出范围");
                throw new Exception("索引超出范围");
            }
        }

        //添加索引器
        public T this[int index]
        {
            get { return array[index]; }
            set { array[index] = value; }
        }

        //插入元素
        public  void Insert(int index,T item)
        {
            if (0 <=index  && index <= Count)
            {
                if (Count == Capacity)
                {
                    //容量不够需要扩容
                    EnsureCapacity();
                }
                //从后往前遍历
                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 (0 <= index && index < Count)
            {
                for (int i = index+1; i < Count; i++)
                {
                    array[i-1] = array[i];
                }
                array[Count - 1] = default(T);
                count--;
            }
            else
            {
                throw new Exception("索引超出范围");
            }
        }

        //顺序查找第一元素
        public int IndexOf(T item)
        {
            for (int i = 0; i < Count; i++)
            {
                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++)
                {
                    if (array[j].CompareTo(array[j + 1]) > 0)
                    {
                        T tempItem = array[j];
                        array[j] = array[j + 1];
                        array[j + 1] = tempItem;
                    }
                }
            }
        }

        public IEnumerator<T> GetEnumerator()
        {
            for (int i = 0; i < Count; i++)
            {
                yield return array[i];
            }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            throw new NotImplementedException();
        }
    }
}


复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享