Пишу свой класс DoubleLinkedList, застрял на реализации IDoubleLinkedList,IEnumerable

Делаю д/з, нужно написать свой класс DoubleLinkedList и реализовать к нему методы И плюс к методам еще реализовать интерфейсы

public class DoubleLinkedList<T> : IDoubleLinkedList<T>,IEnumerable<T>

Много уже информации перелопатил , есть понимание для чего эти интерфейсы нужны а вот как сделать с этим беда полнейшая. Подскажите люди добрые хотя бы в каком направлении двигаться

Интерфейсы в самом низу находятся, заранее за любую помощь огромная благодарность

public class DoubleLinkedList<T> : IDoubleLinkedList<T>,IEnumerable<T>
{
    public int Count { get; set; }
    private Node<T> _root;
    private Node<T> _tail;

    public DoubleLinkedList()
    {
        Count = 0;
        _root = null; 
        _tail = null;
    }

    public DoubleLinkedList(T value)
    {
        Count = 1;
        _root = new Node<T>(value);
        _tail = _root;
    }

    public DoubleLinkedList(T[] values)
    {
        

        if (values.Length != 0)
        {
            Count = values.Length;
            _root = new Node<T>(values[0]);
            _root.Next = null;
            _root.Previous = null;
            _tail = _root;

            for (int i = 1; i < values.Length; i++) 
            {
                var newNode = new Node<T>(values[i]);
                _tail.Next = newNode;
                newNode.Previous = _tail;
                _tail = newNode;
            }
        }
        else
        {
            _root = null;
            _tail = null;
        }
    }
  
    public void PrintList()
    {
        Node<T> runner = _root;
        while (runner != null)
        {
            Console.WriteLine(runner.Value);
            runner = runner.Next;
        }
    }

    public void PrintReverse()
    {
        var item = _tail;
        while (item != null)
        {
            Console.WriteLine($"{item.Value}");
            item = item.Previous;
        }
    }
    public bool isEmpty { get { return Count == 0; } }

    public void AddFirst(T value)
    {
        var node = new Node<T>(value);
        var temp = _root;
        node.Next = _root;            
        _root = node;

        if (Count == 0)
        {
            _tail = _root;
        }
        else
        { 
            temp.Previous = node;
            Count++;
        }                            
    }

    public void AddLast(T value)
    {
        var newNode = new Node<T>(value);
        _tail.Next = newNode;
        newNode.Previous = _tail;
        _tail = newNode;
        Count++;          
    }

    

    public void Clear()
    {
        _root = null;
        _tail = null;
        Count = 0;
    }

    public bool Contains(T data)
    {
        var current = _root;
        while (current != null)
        {
            if (current.Value.Equals(data))
                return true;
            current = current.Next;
        }
        return false;
    }

   

    public bool Remove(T value)
    {
        var current = _root;

        while (current != null)
        {
            if (current.Value.Equals(value))
            {
                break;
            }
            current = current.Next;
        }
        if (current != null)
        {
            if (current.Next != null)
            {
                current.Next.Previous = current.Previous;
            }
            else
            {
                _tail = current.Previous;
            }

            if (current.Previous != null)
            {
                current.Previous.Next = current.Next;
            }
            else
            {
                _root = current.Next;
            }
            Count--;
            return true;
        }
        return false;
    }

    public IEnumerable<T> BackEnumerator()
    {
        throw new NotImplementedException();
    }
    public IEnumerator<T> GetEnumerator()
    {
        throw new NotImplementedException();
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        throw new NotImplementedException();
    }
}

Ответы (1 шт):

Автор решения: aepot

Не понятно, что такое интерфейс IDoubleLinkedList<T>, почему-то вы его не показали, поэтому ответ без учета этого интерфейса.

private IEnumerable<T> GetEnumerable()
{
    Node<T> node = _root;
    while (node != null)
    {
        yield return node.Value;
        node = node.Next;
    }
}

public IEnumerable<T> GetBackEnumerable()
{
    Node<T> node = _tail;
    while (node != null)
    {
        yield return node.Value;
        node = node.Previous;
    }
}

public IEnumerator<T> GetEnumerator()
{
    return GetEnumerable().GetEnumerator();
}

IEnumerator IEnumerable.GetEnumerator()
{
    return GetEnumerable().GetEnumerator();
}

Еще несколько ошибок

public int Count { get; set; }

Вы разрешаете кому угодно менять Count? Я бы так не делал

public int Count { get; private set; }

Свойства надо писать с большой буквы

public bool isEmpty { get { return Count == 0; } }

Получится так

public bool IsEmpty { get { return Count == 0; } }

А еще можно так написать

public bool IsEmpty => Count == 0;

Методы добавления элементов могут выглядеть так

public void AddFirst(T value)
{
    var node = new Node<T>(value);
    if (_root != null)
        _root.Previous = node;
    else
        _tail = node;
    _root = node;
    Count++;
}

public void AddLast(T value)
{
    var node = new Node<T>(value);
    if (_tail != null)
        _tail.Next = node;
    else
        _root = node;
    _tail = node;
    Count++;          
}

С учетом того, что реализуется IEnumerable<T>, вот этот метод не нужен вообще:

public bool Contains(T data)

Данный метод есть в Linq.

Методы

public void PrintList()
public void PrintReverse()

Не должны входить в состав коллекции. Что если я буду использовать ваш список в Winforms или Unity, что я как разработчик должен ожидать от этих методов? Зависимости от окружения в реализации коллекции не должно быть. Если мне надо вывести в консоль, этот список, я воспользуюсь IEnumerable<T>.

foreach (var item in list)
{
    Console.WriteLine(item);
}

Конструктор из коллекции

public DoubleLinkedList(T[] values)

может выглядеть так

public DoubleLinkedList(IEnumerable<T> values)
{
    foreach (T value in values)
    {
        AddLast(value);
    }
}

Кстати, а почему бы не использовать цикл for?

private IEnumerable<T> GetEnumerable()
{
    for (Node<T> node = _root; node != null; node = node.Next)
    {
        yield return node.Value;
    }
}

В итоге получилось что-то такое

public class Node<T>
{
    public T Value { get; set; }
    public Node<T> Next { get; set; }
    public Node<T> Previous { get; set; }

    public Node(T value) 
        => Value = value;
}

public interface IDoubleLinkedList<T>
{
    void AddFirst(T item);
    void AddLast(T item);
    IEnumerable<T> GetBackEnumerable();
}

public class DoubleLinkedList<T> : IDoubleLinkedList<T>, ICollection<T>, IEnumerable<T>
{
    private Node<T> _root;
    private Node<T> _tail;
    private int _count;

    public int Count => _count;
    public bool IsReadOnly => false;

    public DoubleLinkedList() { }

    public DoubleLinkedList(T value) 
        => AddLast(value);

    public DoubleLinkedList(IEnumerable<T> values)
    {
        foreach (T value in values)
            AddLast(value);
    }

    public void AddFirst(T item)
    {
        var node = new Node<T>(item);
        if (_root != null)
            _root.Previous = node;
        else
            _tail = node;
        _root = node;
        _count++;
    }

    public void AddLast(T item)
    {
        var node = new Node<T>(item);
        if (_tail != null)
            _tail.Next = node;
        else
            _root = node;
        _tail = node;
        _count++;
    }

    public void CopyTo(T[] array, int arrayIndex)
    {
        int i = arrayIndex;
        foreach (T value in GetEnumerable())
        {
            if (i >= array.Length)
                break;
            array[i] = value;
        }
    }

    public bool Contains(T item) 
        => GetEnumerable().Contains(item);

    public void Clear()
    {
        _root = null;
        _tail = null;
        _count = 0;
    }

    public bool Remove(T value)
    {
        Node<T> node;
        for (node = _root; node != null; node = node.Next)
            if (node.Value.Equals(value))
                break;

        if (node != null)
        {
            if (node.Previous != null)
                node.Previous.Next = node.Next;
            if (node.Next != null)
                node.Next.Previous = node.Previous;
            _count--;
            return true;
        }
        return false;
    }

    private IEnumerable<T> GetEnumerable()
    {
        for (Node<T> node = _root; node != null; node = node.Next)
            yield return node.Value;
    }

    public IEnumerable<T> GetBackEnumerable()
    {
        for (Node<T> node = _tail; node != null; node = node.Previous)
            yield return node.Value;
    }

    public IEnumerator<T> GetEnumerator() 
        => GetEnumerable().GetEnumerator();

    IEnumerator IEnumerable.GetEnumerator() 
        => GetEnumerable().GetEnumerator();

    void ICollection<T>.Add(T item)
        => AddLast(item);
}

Но ввобще всё, что вы пытаетесь сделать, уже умеет LinkedList<T> - документация.

→ Ссылка