Вы можете определить конструктор вычислений, который скрывает проверку null
, но он не дает вам очень удобного синтаксиса, поэтому я, вероятно, не написал бы его таким образом.Было бы здорово, если бы для этого был более легкий синтаксис, потому что это было бы весьма полезно.Кроме того, построитель вычислений просто распространяет null
, поэтому вы должны получить результат типа Nullable<bool>
:
nullable { let! u = user
let! i = item
return u.Id == i.AuthorId && security.Does(user).Have(MyPermission).On(i) }
Идея состоит в том, что операция let!
вызывает только остальные вычисления.когда аргумент не null
.Когда он равен null
, он сразу возвращает null
в качестве общего результата.
Я не думаю, что вы могли бы многое сделать, чтобы сделать код лучше.Конечно, если все это было написано на F #, то ни одно из значений не могло бы быть null
(поскольку объявленные типы F # не допускают значение null
), но это другая история.
Другой подходв F # было бы объявить активный шаблон , который соответствует только тогда, когда значение не null
.Преимущество этого заключается в том, что в коде не будет переменных, которые могут иметь значение null
, поэтому нет опасности использовать неправильную переменную и получить NullReferenceException
:
let shouldGrantPermission = function
| NotNull(security:ISecurityService), NotNull(user), NotNull(item) ->
security.Does(user).Have(MyPermission).On(item)
| _ -> true
Объявлениеактивного шаблона:
let (|NotNull|_|) a = if a <> null then Some(a) else None
Тем не менее, даже это не намного лучше, чем прямой эквивалент того, что у вас есть.Я думаю, иметь дело со значениями null
это просто боль :-).В этой статье Иена Гриффитса есть некоторые связанные идеи, но, опять же, ни одна из них действительно не решает проблему.