Tak naprawdę na szybko. Pewnie wiele da się tutaj zoptymalizować ale mam inną robotę więc zabawę zostawiam Tobie:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace List
{
class CustomList<T> : IList<T>
{
private class Node
{
public T Item { get; set; }
public int Index { get; set; }
public Node Next { get; set; }
}
private Node root;
private int count;
private bool isReadOnly;
public int IndexOf(T item)
{
for (Node n = this.root; n != null; n = n.Next)
if (n.Item.GetHashCode() == item.GetHashCode()) return n.Index;
return -1;
}
public void Insert(int index, T item)
{
this.isReadOnly = true;
for (Node n = this.root; n != null; n = n.Next)
{
if (n.Index == index)
{
this.count += 1;
var node = new Node { Item = item };
node.Next = n.Next;
n.Next = node;
this.Reindex();
break;
}
}
this.isReadOnly = false;
}
public void RemoveAt(int index)
{
Node temp = this.root;
Node preview = null;
this.isReadOnly = true;
while (temp.Next != null)
{
preview = temp;
temp = temp.Next;
if (temp.Index == index)
{
this.count -= 1;
if (preview != null)
{
preview.Next = temp.Next;
this.Reindex();
}
else this.root = temp.Next;
}
}
this.isReadOnly = false;
}
public T this[int index]
{
get
{
for (Node n = this.root; n != null; n = n.Next)
if (n.Index == index) return n.Item;
return default(T);
}
set
{
for (Node n = this.root; n != null; n = n.Next)
if (n.Index == index) n.Item = value;
}
}
public void Add(T item)
{
var node = new Node { Item = item, Index = this.root != null ? this.root.Index + 1 : 0 };
node.Next = this.root;
this.root = node;
this.count += 1;
}
public void Clear()
{
this.root = null;
}
public bool Contains(T item)
{
for (Node n = this.root; n != null; n = n.Next)
if (n.Item.GetHashCode() == item.GetHashCode()) return true;
return false;
}
public void CopyTo(T[] array, int arrayIndex = 0)
{
var index = arrayIndex;
for (Node n = this.root; n != null; n = n.Next)
{
array[index++] = n.Item;
}
}
public int Count
{
get { return this.count; }
}
public bool IsReadOnly
{
get { return this.isReadOnly; }
}
public bool Remove(T item)
{
Node temp = this.root;
Node preview = null;
this.isReadOnly = true;
while (temp.Item.GetHashCode() != item.GetHashCode() && temp.Next != null)
{
preview = temp;
temp = temp.Next;
}
if (temp.Item.GetHashCode() == item.GetHashCode())
{
this.count -= 1;
if (preview != null)
{
preview.Next = temp.Next;
this.Reindex();
}
else this.root = temp.Next;
this.isReadOnly = false;
return true;
}
this.isReadOnly = false;
return false;
}
public IEnumerator<T> GetEnumerator()
{
for (Node n = this.root; n != null; n = n.Next) yield return n.Item;
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
public void Print()
{
for (Node n = this.root; n != null; n = n.Next)
if (n.Item is string) Console.WriteLine("{0}: {1}", n.Index, n.Item);
Console.WriteLine();
}
public void Reindex()
{
var index = this.count - 1;
for (Node n = this.root; n != null; n = n.Next)
n.Index = index--;
}
}
class Program
{
static void Main(string[] args)
{
var list = new CustomList<string>() { "Tomek", "Rafał", "Maciek", "Grzegorz", "Anna", "Kasia", "Stasia" };
list.Print();
list.Insert(0, "Wstawiony zerowy");
list.Insert(3, "Wstawiony trzeci");
list.Remove("Maciek");
list.Print();
list.Remove("Stasia");
list.Remove("Kasia");
list.Remove("Grzegorz");
list.Print();
list.RemoveAt(1);
list.RemoveAt(0);
list.Print();
list.Add("Karol");
list.Add("Piotrek");
list.Add("Stefan");
list.Add("Sebastian");
list.Add("Monika");
list[3] = "Zmieniony Stefan";
list[0] = "Jakiś Zenon";
list.Print();
list.RemoveAt(list.Count - 1);
list.RemoveAt(0);
list.Print();
Console.WriteLine("Index of Monika: {0}", list.IndexOf("Monika"));
Console.WriteLine("Contains Piotrek: {0}", list.Contains("Piotrek"));
Console.WriteLine("Contains Blabla: {0}", list.Contains("Blabla"));
var array = new string[list.Count + 10];
list.CopyTo(array, 4);
for (int i = 0; i < array.Length; i++) Console.WriteLine("{0}: {1}", i, array[i]);
}
}
}
http://ideone.com/O3M5yN