Rumah pembangunan bahagian belakang Tutorial C#.Net C#基础知识整理 基础知识(16) IList接口——非泛型

C#基础知识整理 基础知识(16) IList接口——非泛型

Feb 11, 2017 pm 01:44 PM

了解了ICollection接口、迭代以及泛型集合,下面再详细了解一下IList接口。
通过MSDN可以看到IList接口有两种:

元素为object类型的IList接口,可以放不同类型的对象引用;
IList泛型接口,只能存放指定类型的对象引用。
其实,IList和IList也称之为向量,特点是可以动态的改变集合的长度,无需确定集合的初始长度,集合会随着存放数据的数量自动变化。
可以看到IList和IList的继承关系:

[ComVisibleAttribute(true)]
public interface IList : ICollection, IEnumerable

public interface IList<T> : ICollection<T>, 
 IEnumerable<T>, IEnumerable
Salin selepas log masuk

现在再返回去看下,IList和IList的区别,看如下代码,ArrayList是继承IList的,List继承IList

   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
    {
    }
Salin selepas log masuk

这下就比较明白了。
一、IList接口概述
ILis接口从ICollection接口继承,具备以下特性,
Count属性——获取集合元素个数;
GetEnumerator方法——可以迭代;
CopyTo方法——将指定元素复制到另一个数组中;
Clear方法——清空整个集合。
IList新增特性,
索引器属性——根据索引访问集合中任意元素;
Add方法——向集合末尾添加元素;
Insert方法——向集合指定位置插入元素;
Remove方法——移除指定元素;(包括RemoveAt)
Contains方法——判断对象是否在集合中;
IndexOf方法——查找指定对象在集合中的索引位置。
另外,IList接口集合按照顺序存放元素,不改变元素存放顺序。
2、算法
向量集合和数组一样,具备随即访问的特点。即无论访问向量集合的任何一个单元,所需的访问时间是完全相同的。在向量类中,实际上依然使用普通数组来记录集合数据,向量类使用了一些算法技巧,让整个类对外表现不同于普通数组的重要特点:可以动态改变数组长度。具体算法如下:
在内部数组足够长的情况下,直接进行添加和插入操作,在内部数组长度不足的情况下,按照内部数组长度增加2倍作为新的数组的长度,然后进行数据搬移(即把就数组数组移到新数组中)。向量在分配元素存储空间时,会多分配一些冗余空间,尽量减少内存分配次数。在数据删除时,并不改变内部数组长度,仅仅是使用被删除数据之后的数据覆盖被删除的数据。
不过向量每次分配空间时都多分配一些冗余空间,会造成内存的压力,因此在程序中应该尽量避免集中的次数繁多的内存分配。
三、实现类
IList和IList的实现类,分别是ArrayList类和List类。
ArrayList类处于System.Collection命名空间下;
List类处于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);
        }
    }
Salin selepas log masuk


调用测试:

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();
        }
Salin selepas log masuk

结果:

以上就是的内容,更多相关内容请关注PHP中文网(www.php.cn)!

 

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

AI Hentai Generator

AI Hentai Generator

Menjana ai hentai secara percuma.

Artikel Panas

R.E.P.O. Kristal tenaga dijelaskan dan apa yang mereka lakukan (kristal kuning)
2 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
Repo: Cara menghidupkan semula rakan sepasukan
4 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: Cara mendapatkan biji gergasi
4 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Apakah alternatif untuk membatalkan bahasa C Apakah alternatif untuk membatalkan bahasa C Mar 03, 2025 pm 05:37 PM

Artikel ini meneroka cabaran penentuan penunjuk null dalam C. Ia berpendapat bahawa masalah itu tidak batal sendiri, tetapi penyalahgunaannya. Artikel ini memperincikan amalan terbaik untuk mencegah dereferensi, termasuk pemeriksaan pra-pengertian, penunjuk inisial

Cara menambah pengkompil C peringkat seterusnya Cara menambah pengkompil C peringkat seterusnya Mar 03, 2025 pm 05:44 PM

Artikel ini menerangkan cara membuat aksara baru dalam C menggunakan urutan \ n Escape dalam Printf dan meletakkan fungsi. Ia memperincikan fungsi dan menyediakan contoh kod yang menunjukkan penggunaannya untuk pecah talian dalam output.

Penyusun bahasa C mana yang lebih baik? Penyusun bahasa C mana yang lebih baik? Mar 03, 2025 pm 05:39 PM

Artikel ini membimbing pemula untuk memilih pengkompil C. Ia berpendapat bahawa GCC, kerana kemudahan penggunaannya, ketersediaan yang luas, dan sumber yang luas, adalah yang terbaik untuk pemula. Walau bagaimanapun, ia juga membandingkan GCC, Clang, MSVC, dan TCC, yang menonjolkan perbezaan mereka

Adakah Null masih penting dalam pengaturcaraan moden dalam bahasa C? Adakah Null masih penting dalam pengaturcaraan moden dalam bahasa C? Mar 03, 2025 pm 05:35 PM

Artikel ini menekankan kepentingan berterusan null dalam pengaturcaraan C moden. Walaupun kemajuan, null tetap penting untuk pengurusan penunjuk yang jelas, mencegah kesalahan segmentasi dengan menandakan ketiadaan alamat memori yang sah. Prac terbaik

Apakah versi web penyusun bahasa C? Apakah versi web penyusun bahasa C? Mar 03, 2025 pm 05:42 PM

Artikel ini mengkaji semula penyusun dalam talian untuk pemula, memberi tumpuan kepada kemudahan penggunaan dan keupayaan debug. Onlineegdb dan Repl.It diserlahkan untuk antara muka mesra pengguna dan alat debugging yang berguna. Pilihan lain seperti programz dan penyusunan

C Laman Web Pengaturcaraan Dalam Talian C Ringkasan Laman Web Rasmi C Laman Web Pengaturcaraan Dalam Talian C Ringkasan Laman Web Rasmi Mar 03, 2025 pm 05:41 PM

Artikel ini membandingkan platform pengaturcaraan dalam talian C, menonjolkan perbezaan ciri -ciri seperti alat debugging, fungsi IDE, pematuhan standard, dan had memori/pelaksanaan. Ia berpendapat bahawa platform "terbaik" bergantung kepada keperluan pengguna,

Kaedah Penyalinan Kod oleh Compiler Bahasa C Kaedah Penyalinan Kod oleh Compiler Bahasa C Mar 03, 2025 pm 05:43 PM

Artikel ini membincangkan penyalinan kod yang efisien dalam c ides. Ia menekankan bahawa penyalinan adalah fungsi IDE, bukan ciri pengkompil, dan strategi butiran untuk kecekapan yang lebih baik, termasuk menggunakan alat pemilihan IDE, lipatan kod, carian/menggantikan, templa

Cara menyelesaikan masalah tidak muncul tetingkap output oleh pengkompil bahasa C Cara menyelesaikan masalah tidak muncul tetingkap output oleh pengkompil bahasa C Mar 03, 2025 pm 05:40 PM

Artikel ini menyelesaikan masalah tingkap output yang hilang dalam kompilasi program C. Ia meneliti sebab -sebab seperti gagal menjalankan kesilapan, kesilapan program, tetapan penyusun yang salah, proses latar belakang, dan penamatan program yang cepat. Penyelesaian melibatkan ch

See all articles