вне параметров с обнуляемыми ссылочными типами - PullRequest
0 голосов
/ 13 декабря 2018

Я реализовал тип Option для некоторого моего проекта, подобного этому:

public abstract Option<T> {}

public class None<T> : Option<T>

public class Some<T> : Option<T> 
{
    public T Value { get; }

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

Чтобы узнать, содержит ли Option значение, я использую этот метод расширения, который использует сопоставление с шаблоном:

public static bool TryGetValue<T>(this Option<T> option, out T value)
{
    if (option is Some<T> some)
    {
        value = some.Value;
        return true;
    }

    value = default;
    return false;
}

Теперь я получаю следующее предупреждение для return default;

Невозможно преобразовать нулевой литерал в необязательный параметр ссылки или неограниченного типа

Этодля меня невозможно ограничить общий параметр T до class или struct.

Например, если я ограничил универсальный параметр значением class, я не смог бы сгенерировать Option<int?> экземпляров, поскольку тип Nullable<int> сам по себе struct.Объявление параметра out как обнуляемого с помощью постфикса ? также не является решением, как кажется.

Для меня система типов на данном этапе несколько нарушена или не совсем продумана.Либо Nullable должен был быть class, либо должно быть ограничение общего параметра, например:

public static bool TryGetValue<T>(this Option<T> option, out T value) 
    where T : nullable [...]

Есть ли другой подход, который может подойти для этой проблемы?Чего мне не хватает?

1 Ответ

0 голосов
/ 31 марта 2019

Если вы просто хотите получить это для компиляции, то вы можете использовать оператор !:

public static bool TryGetValue<T>(this Option<T> option, out T value)
{
    if (option is Some<T> some)
    {
        value = some.Value;
        return true;
    }

    value = default!;
    return false;
}

К сожалению, это будет означать, что T не равно нулю, даже когда это может быть.

Однако, если вы всегда будете правильно использовать шаблон Try (т. Е. Проверяете возвращаемое значение TryGetValue перед использованием параметра out), вы никогда не увидите, что это значение будет нулевым (если T не является на самом деле обнуляемым типом)., в таком случае ты все равно в порядке).

...