При работе со ссылочными типами и типами значений F # ведет себя так же, как C #.
- Если у вас есть ссылочный тип, он работает со ссылкой на экземпляр в куче.
- Если у вас есть тип значения (встроенный, объявленный в C # или объявленный в F # с использованием атрибута
Struct
),
значение копируется, когда вы присваиваете ему другое значение или передаете в качестве аргумента.
Единственное заметное отличие состоит в том, что стандартные типы F # (различимые объединения, записи, списки, массивы и кортежи) имеют структурное равенство семантика. Это означает, что они сравниваются путем сравнения фактического значения, хранящегося в них, а не путем сравнения ссылок (даже если они являются ссылочными типами). Например, если вы создаете два списка кортежей, содержащих одинаковые данные, вы получаете:
> let l1 = [ ("Hello", 0); ("Hi", 1) ]
let l2 = [ ("Hi", 1); ("Hello", 0) ] |> List.rev;;
(...)
> l1 = l2;;
val it : bool = true
Вы получаете true
, хотя списки и кортежи являются ссылочными типами. Однако, если вы сравните ссылки ( РЕДАКТИРОВАТЬ: Добавлен образец, вдохновленный kvb ):
> System.Object.ReferenceEquals(l1, l2);;
val it : bool = false
Использование структурного равенства имеет смысл в F #, потому что типы неизменны - когда вы создаете два значения, содержащие одинаковые данные, они всегда будут одинаковыми. Если бы они были изменяемыми, вы могли бы изменить их, и они больше не были бы равными - поэтому имеет смысл использовать равенство ссылок для изменяемых типов.