NullPointerException в while(!=null) IEnumerator

174
05 февраля 2018, 02:45

Решил сделать реализацию LinkedList, используя IEnumerable. Проблема как раз-таки в нем. У меня есть метод Contains(..),где при использовании foreach исключений не возникает. Есть метод AddAfter(..), где исключение возникает. Меня сбивают с толку две вещи:

  1. Исключение возникает в цикле while(currentNode!=null) (но вылет происходит при currentNode==null)

  2. Программа не вылетает при запуске без отладки, хотя в настройках исключений сказано "прерывать работу"

Вот эти функции:

public IEnumerator <T> GetEnumerator()
    {
        currentNode = firstNode;
        while (currentNode != null)
        {
            yield return currentNode.Data;
            currentNode = currentNode.Next;
        }
    }
public bool Contains(T item)
    {
        foreach (var t in this)
        {
            if (t.Equals(item))
                return true;
        }
        return false;
    }
public bool AddAfter(T item, T after)
    {
        if (this.Contains(item))
        {
            return false;
        }
        foreach (var t in this) // где-то здесь вылетает
        {
            if (t.Equals(after))
            {
                currentNode.Next = new Node <T>(item, currentNode, currentNode.Next);
                if (currentNode == lastNode)
                    lastNode = lastNode.Next;
                return true;
            }
        }
        lastNode.Next = new Node <T>(item, lastNode, null);
        lastNode      = lastNode.Next;
        return true;
    }

Отладчик проходит Contains() без вопросов, но на foreach показывает проблему. В режиме без отладки NullPointerException программу не останавливает(или просто не появляется), и она спокойно перешагивает foreach, и появляются неверные данные. Может, я как-то не правильно понимаю yield return? Я так понимаю, что при первом заходе в функцию выполнятся все строки до yield return. При втором выполнится строка за yield, и программа пойдет дальше по циклу. Тогда выходит, что currentNode между заходами обнуляется?

Вылет: Настройки исключений:

Это еще не все. Если запустить отладку, но при этом пошагово не заходить в этот проблемный foreach, то, опять же, исключений не возникает, и программа выводит как раз-таки ожидаемые результаты. Но если при отладке зайди в этот foreach, то будет исключение, как на втором скриншоте. Как это вообще работает?

Заполняю я весь этот список так:

var tb = TextField; // textBox
        var list = new MyGenListUnique <int>();
        list.AddRange(new []{0,1,2,3,4,5,6,7});
        tb.AppendText(list.ToString() + Environment.NewLine); 
        list.AddAfter(-12, 2); // {0,1,2, -12, 3,4,5,6,7} // проблема здесь
        tb.AppendText(list.ToString() + Environment.NewLine); 

Вот функции добавления и связанные с ними:

public int AddRange(T[] items)
    {
        if (items is null)
        {
            return 0;
        }
        var countAdded = 0;
        foreach (var t in items)
        {
            var currCount = Count;
            Add(t);
            if (currCount > Count)
                countAdded++;
        }
        return countAdded;
    }
public void Add(T item)
    {
        if (firstNode is null)
        {
            firstNode = new Node <T>(item, null, null);
            lastNode  = firstNode;
            return ;
        }
        if (!this.Contains(item))
        {
            lastNode.Next = new Node <T>(item, lastNode, null);
            lastNode      = lastNode.Next;
            IncreaseCount();
            return ;
        }
    }
public new string ToString()
    {
        var sb = new StringBuilder(100);
        sb.Append("{ ");
        foreach (var t in this)
        {
            sb.Append(t + " ");
        }
        sb.Append("}");
        return sb.ToString();
    }
private void IncreaseCount(int count = 1)
    {
        Count += count;
    }

Count - autoproperty, конструктор по умолчанию - пустой. Если что, вот класс Node<T>

private class Node <T>
    { 
        public T Data;
        public Node <T> Next { get; set; }
        public Node <T> Prev { get; set; }
        public Node() {}
        public Node(T data, Node <T> prev, Node <T> next)
        {
            Data = data;
            Next = next;
            Prev = prev;
        }  
    }
READ ALSO
Task&lt;T&gt; вернуть null, не прерывая задачу

Task<T> вернуть null, не прерывая задачу

Одна задача, ожидает выполнение другой задачи, как только возвращаем null из ожидаемой задачи, происходит прерывание выполнения другой

178
сброс цикла по алфавиту

сброс цикла по алфавиту

Уже спрашивал этот вопросно все-таки есть одна проблема

196
Как скомпилировать все проекты солюшена в один .EXE?

Как скомпилировать все проекты солюшена в один .EXE?

Есть солюшен (Solution)В нем 4 проекта

180
C# TCP Отправить hex

C# TCP Отправить hex

Как отправить в C# hex а не string на tcp? Использую для проверки програму-клиент-сервер и если конвертировать string в байты то эта программа получит...

167