F # — использование Concurrent.ConcurrentDictionary.Попробуйте удалить с помощью dotnet 5

#.net #f# #c#-to-f#

#.net #f# #c #-to-f#

Вопрос:

Я переношу свой код F # с dotnet3.1 на 5 и борюсь со следующим кодом:

         let tryRemove key (dict: Concurrent.ConcurrentDictionary<'a, 'b>) =
           match dict.TryRemove(key) with
           | (true, v) -> Some v
           | (false, _) -> None
 

В версии 3.1 TryRemove возвращаемый кортеж, в версии 5 он возвращает только логическое значение. Чтобы получить значение из словаря, мне нужно передать ссылку в качестве второго параметра TryRemove .
Как правильно это сделать и избежать возврата null v?

Я попробовал следующий код:

     let tryRemove key (dict: Concurrent.ConcurrentDictionary<'a, 'b>): 'b option =
       let mutable v: 'b = null
       match dict.TryRemove(key, amp;v) with
       | true -> Some v
       | _ -> None
 

Но теперь функция, которая его использует, считает, что внутри этой опции можно иметь значение null из tryRemove

ошибка FS0001: тип ‘(Body -> unit)’ не имеет ‘null’ в качестве правильного значения

где b' is (Body -> unit)

Ответ №1:

Проблема в том, что .NET 5 добавил перегрузку. Раньше была только TryRemove (key : 'a, byref<'b> value) : bool , теперь TryRemove(item: KeyValuePair<'a, 'b>) : bool выбирается новая перегрузка. Смотрите netcore 3.1 против NET 5

Альтернативным решением является добавление аннотации типа, например

 let tryRemove (key: 'a) (dict: Concurrent.ConcurrentDictionary<'a, 'b>) =
   match dict.TryRemove(key) with
   | (true, v) -> Some v
   | (false, _) -> None
 

Ответ №2:

Я только что выяснил:

 let mutable v = Unchecked.defaultof<'b>
 

вместо

 let mutable v: 'b = null
 

работает, но это очень странно. упрощенный синтаксис с последним аргументом out, переведенным в результат кортежа, больше не работает. Так ли это?

РЕДАКТИРОВАТЬ
Это все еще работает! Смотрите правильный ответ 🙂