Для примера программы:
type public MyClass(reasonForLiving:string) =
member x.ReasonForLiving with get() = reasonForLiving
let classFactory () = MyClass("up to you")
let live () =
let instance = classFactory()
if instance = null then raise(System.Exception("null is not living... that why OO languages die from bugs"))
instance
Я получаю сообщение об ошибке "Тип MyClass не имеет нулевого значения в качестве правильного значения", когда я использую этот класс как возвращаемое значение неявно типизированных функций и сравниваю его с нулевым (b/c требований совместимости с С# зависимая инъекция Я не могу полагаться на типы опций F #).
Я легко могу исправить это, изменив нулевую проверку на:
if instance :> obj = null then
Однако, я знаю ( "чувствую" ), это полностью "неправильно". Особенно, когда я рассматриваю, как MyClass является ссылочным типом, который не нужно вставлять в бокс (говоря с фона С#).
Я читал о "Ограничении значения F #" и о том, как он влияет на вывод типа, но я не могу понять, как он относится к этому сценарию.
Q: Есть ли другой способ сделать это?
Помимо # 1: я нашел более простой способ получения ошибки...
type public MyClass(reasonForLiving:string) =
member x.ReasonForLiving with get() = reasonForLiving
let nullMyClass : MyClass = null
Помимо # 2: я попробовал System.Nullable, не задумываясь... MyClass - это ссылочный тип, а не тип значения (struct), который требуется Nullable < _ > . Итак, просто успокаивает меня, что я ДЕЙСТВИТЕЛЬНО имею дело с ссылочным типом, и оставляет меня в недоумении, почему внезапно этот объект делает эту работу.
Обновление:. Для всех, кого это интересует, я использовал это как одно решение для Common Service Locator с тремя функциями ниже. Каждая запрошенная служба должна поддерживать нуль, поэтому, если класс службы определен в F #, вам нужно добавить [<AllowNullLiteral>]
:
let private getServiceLocator () =
try Some(Microsoft.Practices.ServiceLocation.ServiceLocator.Current)
with | _ -> None
let private getService serviceFactory =
let serviceLocator = getServiceLocator()
let service = match serviceLocator with
| None -> serviceFactory()
| _ ->
match serviceLocator.Value.GetInstance<'a>() with
| null -> serviceFactory()
| svc -> svc
match service with
| null -> None
| _ -> Some(service)
let private getRequiredService serviceFactory =
let service = getService serviceFactory
match service with
| None -> raise(MissingServiceException(""))
| _ -> service.Value