This article mainly shows the imitation List source code to achieve a custom List class, to understand C# has some help.
Based on the content
Add() adds the element at the end
Insert() specifies the subscript to Insert the element
The Count attribute indicates the number of elements
The RemoveAt() method specifies the subscript element to be removed
IndexOf() returns the IndexOf the first element
LastIndexOf() returns the index of the last element
Implement a basic List with a generic array
First, define the MyList class
class MyList<T>
{
private T[] array;// Generic arrays are used to store data as the body of the class
private int count = 0;// Store the number of elements
public MyList(int size)
{
array = new T[size];
}
public MyList()
{
array = new T[0]; }}Copy the code
To complete class initialization, add two constructors here. The constructor with no arguments creates an array of length zero, and the constructor with arguments builds an array of specified length.
// Obtain the capacity
public int Capacity { get => array.Length; }
public int Count { get => count; }
Copy the code
Set the accessor and encapsulate the count field, which the object can use to get the number of list elements by calling the count attribute. The second part implements the Add method
public void Add(T item)
{
if( Count == Capacity)// Whether the maximum capacity is reached
{
if(Capacity == 0)
{
array = new T[4];
}
else
{
EnsureCapacity();
}
}
array[Count] = item;
count++;
}
private void EnsureCapacity()
{
// If the capacity is insufficient, double the capacity each time
var newArray = new T[Capacity * 2];
Array.Copy(array, newArray, Count);
array = newArray;
}
Copy the code
When the capacity is insufficient when adding elements to the array, the capacity is expanded by twice the current capacity. Create a new array that is twice the size, and then copy the original array members into the new array. Add indexers If you want list objects to be accessible using [] like arrays, you must add indexers.
// Add indexer
public T this[int index]
{
get { return array[index]; }
set { array[index] = value; }}Copy the code
The Insert method needs to understand that the subscript is out of bounds, and the capacity is sufficient to Insert the element. We move the elements from the end to index one by one and assign item to the number of elements at index by one
// Insert the element
public void Insert(int index,T item)
{
if (0 <=index && index <= Count)
{
if (Count == Capacity)
{
// The capacity is insufficient
EnsureCapacity();
}
// Iterate from back to front
for (int i = Count- 1; i >= index; i--)
{
array[i+1] = array[i];
}
array[index] = item;
count++;
}
else
{
throw new Exception("Index out of range"); }}Copy the code
Implement the RemoveAt method the RemoveAt method is similar to the Insert method. We’re going to move the elements forward one by one starting at index and we’re going to set the last element to the default and subtract one from the number of elements
// Delete the specified element
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("Index out of range"); }}Copy the code
To find the first identical element, return the index. Generics cannot be compared using the comparison operator. Just use the Equals method of the array.
// Find the first element in order
public int IndexOf(T item)
{
for (int i = 0; i < Count; i++)
{
if (array[i].Equals(item))
{
returni; }}return - 1;
}
// Find the first element in reverse order
public int LastIndexOf(T item)
{
for (int i = Count- 1; i >=0 ; i--)
{
if (array[i].Equals(item))
{
returni; }}return - 1;
}
Copy the code
Implement sorting using bubble sort when comparing two generic elements, you must provide the generic constraints of IComparable if you use the CompaerTo method
class MyList<T> where T:IComparable{}
Copy the code
// Sort in ascending order
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; }}}}Copy the code
You can use yield to simplify iterators. You can only implement IEnumerable
class MyList<T> :IEnumerable<T> where T:IComparable{}
Copy the code
public IEnumerator<T> GetEnumerator()
{
for (int i = 0; i < Count; i++)
{
yield return array[i];
}
}
IEnumerator IEnumerable.GetEnumerator()
{
throw newNotImplementedException(); }}Copy the code
Clear, so you can forch the list object.
The complete code
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];
}
// Obtain the capacity
public int Capacity { get => array.Length; }
public int Count { get => count; }
public void Add(T item)
{
if( Count == Capacity)// Whether the maximum capacity is reached
{
if(Capacity == 0)
{
array = new T[4];
}
else
{
EnsureCapacity();
}
}
array[Count] = item;
count++;
}
private void EnsureCapacity()
{
// If the capacity is insufficient, double the capacity each time
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(" index out of range ");
throw new Exception("Index out of range"); }}// Add indexer
public T this[int index]
{
get { return array[index]; }
set { array[index] = value; }}// Insert the element
public void Insert(int index,T item)
{
if (0 <=index && index <= Count)
{
if (Count == Capacity)
{
// The capacity is insufficient
EnsureCapacity();
}
// Iterate from back to front
for (int i = Count- 1; i >= index; i--)
{
array[i+1] = array[i];
}
array[index] = item;
count++;
}
else
{
throw new Exception("Index out of range"); }}// Delete the specified element
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("Index out of range"); }}// Find the first element in order
public int IndexOf(T item)
{
for (int i = 0; i < Count; i++)
{
if (array[i].Equals(item))
{
returni; }}return - 1;
}
// Find the first element in reverse order
public int LastIndexOf(T item)
{
for (int i = Count- 1; i >=0 ; i--)
{
if (array[i].Equals(item))
{
returni; }}return - 1;
}
// Sort in ascending order
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 newNotImplementedException(); }}}Copy the code