Re[4]: C# [Proposal] init block for safe initialization of c
От: Sinclair Россия https://github.com/evilguest/
Дата: 26.12.25 05:30
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>то есть вызвать нелокальные функции в обработке property.set он может

Не очень понял, что вы имеете в виду. Можно пример?
SP>Или может я не понял, что имеется в виду под локальными функциями? Локальные в модуле, классе, функции?
В примере это локальная функция, объявленная по месту. См. Example 2.

S>>Попробуйте переписать пример с использованием Optional. Станет хуже


SP>переписал. Не вижу, что стало хуже


SP>
SP>using System;
SP>using System.Collections.Generic;
SP>using Optional;

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

SP>    public Node(T value)
SP>    {
SP>        Value = value;
SP>        Next = Option.None<Node<T>>();
SP>        Previous = Option.None<Node<T>>();
SP>    }

SP>    public static Option<Node<T>> Init<T>(IEnumerable<T> values)
SP>    {
SP>        using var enumerator = values.GetEnumerator();
SP>        if (!enumerator.MoveNext())
SP>            return Option.None<Node<T>>();

SP>        var head = new Node<T>(enumerator.Current);
SP>        var current = head;

SP>        while (enumerator.MoveNext())
SP>        {
SP>            var newNode = new Node<T>(enumerator.Current);

SP>            current.Next = Option.Some(newNode);
SP>            newNode.Previous = Option.Some(current);

SP>            current = newNode;
SP>        }

SP>        return Option.Some(head);
SP>    }

SP>    public static IEnumerable<T> TraverseForward<T>(Option<Node<T>> start)
SP>    {
SP>        var current = start;

SP>        while (current.Match(
SP>            some: node =>
SP>            {
SP>                yield return node.Value;
SP>                current = node.Next;
SP>                return true;
SP>            },
SP>            none: () => false
SP>        )) { }
SP>    }
SP>}
SP>

Это означает, что логику проверки на Some/None нужно тащить по всему коду. Если уж этим задуряться, то проверки на null компактнее и лучше читаются:
using System;
using System.Collections.Generic;

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

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

    public static Node<T>? Init<T>(IEnumerable<T> values)
    {
        using var enumerator = values.GetEnumerator();
        if (!enumerator.MoveNext())
            return null;

        var head = new Node<T>(enumerator.Current);
        var current = head;

        while (enumerator.MoveNext())
        {
            var newNode = new Node<T>(enumerator.Current);

            current.Next = newNode;
            newNode.Previous = current;

            current = newNode;
        }

        return Option.Some(head);
    }

    public static IEnumerable<T> TraverseForward<T>(Node<T>? start)
    {
        var current = start;

        while (current)
        {
             yield return node.Value;
             current = node.Next;
        }
    }
}


SP>ну вот привёл код выше. Чем секция init будет лучше? Позволит писать компактнее — спорно. Безопаснее — да нисколько.

У вас в коде Init ошибка. Секция init будет лучше тем, что обнаружит её на этапе компиляции.
SP>В общем motivation должен быть в виде сравнения. Вот у меня был такой workaround, а вот так получается с init блоком. Второй вариант очевидно лучше по следующим причинам ... Сейчас лично мне совсем не очевидно.
Вроде такой motivation как раз и приведён.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Отредактировано 26.12.2025 5:35 Sinclair . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.