Я пытаюсь создать тип, похожий на Rust Result
или Haskell, Either
и я дошел до этого:
public struct Result<TResult, TError>
where TResult : notnull
where TError : notnull
{
private readonly OneOf<TResult, TError> Value;
public Result(TResult result) => Value = result;
public Result(TError error) => Value = error;
public static implicit operator Result<TResult, TError>(TResult result)
=> new Result<TResult, TError>(result);
public static implicit operator Result<TResult, TError>(TError error)
=> new Result<TResult, TError>(error);
public void Deconstruct(out TResult? result, out TError? error)
{
result = (Value.IsT0) ? Value.AsT0 : (TResult?)null;
error = (Value.IsT1) ? Value.AsT1 : (TError?)null;
}
}
Учитывая, что параметры обоих типов ограничены notnull
, почему он жалуется (где бы то ни было, где есть параметр типа со ?
знаком NULL) после него:
Параметр типа Nullable должен быть известен как тип значения или необнуляемый ссылочный тип. Попробуйте добавить ограничение «класс», «структура» или тип.
?
Я использую C # 8 в .NET Core 3 с включенными обнуляемыми ссылочными типами.
c#
generics
type-constraints
c#-8.0
nullable-reference-types
Чистка Диаменте
источник
источник
Ответы:
По сути, вы просите что-то, что не может быть представлено в IL. Типы значений Nullable и ссылочные типы Nullable очень разные звери, и хотя они выглядят одинаково в исходном коде, IL сильно отличается. Обнуляемой версией типа значения
T
является другой тип (Nullable<T>
), тогда как обнуляемой версией ссылочного типаT
является тот же тип, а атрибуты сообщают компилятору, чего ожидать.Рассмотрим этот более простой пример:
Это неверно по той же причине.
Если мы ограничиваемся
T
структурой, то IL, сгенерированный дляGetNullValue
метода, будет иметь тип возвратаNullable<T>
.Если мы ограничиваемся
T
ссылочным типом, не допускающим обнуление, то IL, сгенерированный дляGetNullValue
метода, будет иметь возвращаемый типT
, но с атрибутом для аспекта обнуляемости.Компилятор не может сгенерировать IL для метода, который имеет возвращаемый тип одновременно
T
иNullable<T>
одновременно.В основном это все результат того, что ссылочные типы, которые можно обнулять, вообще не являются концепцией CLR - это просто магия компилятора, которая поможет вам выразить намерения в коде и заставить компилятор выполнить некоторую проверку во время компиляции.
Сообщение об ошибке не так ясно, как могло бы быть.
T
Известно, что это «тип значения или необнуляемый ссылочный тип». Более точное (но значительно более простое) сообщение об ошибке:В этот момент ошибка разумно применима к нашему коду - параметр типа «не известен как тип значения» и не «известен как ненулевой ссылочный тип». Он известен как один из двух, но компилятор должен знать, какой именно .
источник
Nullable<T>
это особый тип, который вы не можете сделать сами. И еще есть бонусный момент, как бокс делается с нулевыми типами.Причина предупреждения объясняется в разделе
The issue with T?
« Опробовать допустимые типы ссылок» . Короче говоря, если вы используете,T?
вы должны указать, является ли тип классом или структурой. Вы можете создать два типа для каждого случая.Более глубокая проблема заключается в том, что использование одного типа для реализации Result и хранения значений Success и Error возвращает те же проблемы, что Result должен был исправить, и еще несколько.
Результат (и любой другой) в F #
Отправная точка должна быть тип результата F # и различимые объединения. В конце концов, это уже работает на .NET.
Тип результата в F #:
Сами типы несут только то, что им нужно.
DU в F # допускают исчерпывающее сопоставление с образцом без нуля:
Эмулируя это в C # 8
К сожалению, в C # 8 еще нет DU, они запланированы на C # 9. В C # 8 мы можем подражать этому, но мы теряем исчерпывающее соответствие:
И использовать это:
Без исчерпывающего сопоставления с образцом мы должны добавить это предложение по умолчанию, чтобы избежать предупреждений компилятора.
Я все еще ищу способ получить исчерпывающее соответствие, не вводя мертвые значения, даже если они являются просто опцией.
Опция / Может быть,
Создать класс Option с помощью исчерпывающего сопоставления проще:
Который может быть использован с:
источник