Здравствуйте, Serginio1, Вы писали:
S>Sinclair не читатель.
Нет, это Serginio1 не читатель.
S>Еще раз какой узел следующий для последнего узла?
Зависит от используемых инвариантов. Например, у "последнего" узла следующим может быть null.
Это позволяет, к примеру, делать простое итерирование:
public static IEnumerable<Node> EnumerateForward(Node? list) {
while (list) {
yield return list;
list = list.Next;
}
}
Это работает, если для нас такая топология является нормальной. В такой топологии никакой пользы от EmptyNode нету.
Если нет, то у нас совсем другой инвариант — за нодой должна идти валидная нода. И в ней тоже нет никакой пользы от EmptyNode.
S> Empty нужны для обозначения, что этот объект дефолтный. У него можно вызвать методы, получить свойства.
Я вам в третий раз пишу: дефолтные объекты не помогают решить проблему, сформулированную Владом. У него проблема не в том, что у null нельзя вызывать методы или получать свойства.
S>Так же его нельзя присваивать свойствам которые должны иметь недефолтные значения и это проверяется в сеттерах или конструкторах.
Прекрасно. Попробуйте запретить присваивание EmptyNode в сеттерах Next и Previous. Получите нерабочий код.
И вообще — вы переносите проверку в рантайм, а смысл не в том, чтобы неверный код падал при исполнении. Он и так падает при исполнении.
И делать проверки на null в конструкторе мы умели ещё четыре версии языка назад:
this.next = next ?? throw new ArgumentNullException(nameof(next))
S>Можно помечать такие свойства атрибутами и проверять через SG
Это по-прежнему не решает исходную задачу.
S> Все тоже, что и со string.Empty