Итак, как я понял из комментариев, ваш фактический вопрос был таким:
Почему возвращаемый объект отличается от переданного?
Прежде всего, ожидание ссылочной идентичности для значений, которые логически "равны", значительно переоценено. Если ваша программа основана на ссылочной идентичности, вы делаете это неправильно. Если вам нужно, чтобы ссылочная идентичность сохранялась повсюду, вы получите Java.
Действительно, попробуйте это:
> obj.ReferenceEquals( 5, 5 )
it : bool = false
> obj.ReferenceEquals( [1;2;3], [1;2;3] )
it : bool = false
А?
Конечно, в некоторых особых случаях вы можете получить true
, например:
> let l = [1,2,3]
> obj.ReferenceEquals( l, l )
it : bool = true
Но это просто совпадение, вытекающее из конкретной реализации, которую компилятор выбрал для представления вашего кода. Не надейся на это.
Во-вторых , ваша функция делает , фактически, возвращает "тот же" (в смысле ссылочной идентичности) объект. Попробуйте это:
> let x =
let array = [||]
let typedArray : int[] = array
let actual = func typedArray
obj.ReferenceEquals( actual, typedArray )
x : bool = true
Видите, как исчезла "неисправность", как только я создал промежуточное звено typedArray
? Вы даже можете заменить int
на IComparable
, это все равно будет true
.
Секрет в том, что функция func
действительно хороша: она возвращает «тот же» объект.
Создание нового объекта происходит не внутри func
, а каждый раз, когда вы ссылаетесь на array
.
Попробуйте это:
> let x =
let array = [||]
obj.ReferenceEquals( array, array )
x : bool = false
А? WTF?!
Это происходит потому, что array
на самом деле не объект, а функция за кадром. Поскольку вы не указали тип array
, он должен быть generic , т. Е. Иметь любой тип, который должен иметь пользователь. Это должно работать:
let array = [||]
let a : int[] = array
let b : string[] = array
Очевидно, что array
не может одновременно иметь тип int[]
и тип string[]
, поэтому единственный способ реализовать такую конструкцию - это скомпилировать ее как функцию , которая не принимает никаких значений параметров , но параметр одного типа. Вроде как это:
static a[] array<a>() { return new a[0]; }
А затем используйте эту функцию для построения a
и b
:
var a = array<int>();
var b = array<string>();
И это именно то, что делает компилятор. Функция, которая принимает только параметры типа, в этом контексте ее можно назвать «функцией типа». И действительно, именно так это называется в скомпилированном коде - FSharpTypeFunc
.