Как я уже сказал в своем комментарии, ваш код C # не будет делать то, что вы хотите (т.е. объединять символы в строку).В C # добавление char
и char
приведет к int
.Причина этого заключается в том, что тип char
не определяет оператор +
, поэтому C # возвращается к ближайшему совместимому типу, который имеет значение, которое просто оказывается int
.( Источник )
Итак, чтобы выполнить это поведение, вам нужно будет сделать нечто похожее на то, что вы уже пытаетесь сделать в F #:
char a = 'a';
char b = 'b';
// This is the wrong way to concatenate chars, because the
// chars will be treated as ints and the result will be 195.
Console.WriteLine(a + b);
// These are the correct ways to concatenate characters into
// a single string. The result of all of these will be "ab".
// The third way is the recommended way as it is concise and
// involves creating the fewest temporary objects.
Console.WriteLine(a.ToString() + b.ToString());
Console.WriteLine(Char.ToString(a) + Char.ToString(b));
Console.WriteLine(new String(new[] { a, b }));
(См. https://dotnetfiddle.net/aEh1FI)
F # аналогичен тому, что объединение двух или более char
s не приводит к String
. В отличие от C #, вместо этого получается другой char
, нопроцесс тот же - значения char
обрабатываются как int
и складываются вместе, и в результате получается char
представление суммы.
Так что на самом деле способ объединения char
s в String
в F # - это то, что у вас уже есть, и является прямым переводом эквивалента C #:
let a = 'a'
let b = 'b'
// This is still the wrong way (prints 'Ã')
printfn "%O" (a + b)
// These are still the right ways (prints "ab")
printfn "%O" (a.ToString() + b.ToString())
printfn "%O" (Char.ToString(a) + Char.ToString(b))
printfn "%O" (String [| a;b |]) // This is still the best way
(см. https://dotnetfiddle.net/ALwI3V)
Причина, по которойПодход «строка из символьного массива» - это лучший способ, состоящий из двух частей. Во-первых, он наиболее краткий, поскольку вы можете видеть, что этот подход предлагает самую короткую строку кода на обоих языках (и разница увеличивается только по мере добавленияи более char
с). И во-вторых, только один временный объектсозданный (массив) перед финальным String
, тогда как два других метода включают создание двух отдельных временных String
объектов для подачи в конечный результат.
(Кроме того, я не уверен, работает ли он таким образом, поскольку конструкторы String
скрыты во внешних источниках, но я представляю, что массив, переданный в конструктор, будет использоваться как *Данные поддержки 1042 *, поэтому они не будут потрачены впустую.) String
являются неизменными, но использование переданного массива напрямую, поскольку созданные данные поддержки String
могут привести кСитуация, когда ссылка на массив может храниться в другом месте программы и поставить под угрозу неизменность String
, поэтому это предположение не будет реализовано на практике.(Credit: @CaringDev)
Еще один вариант, который вы можете сделать в F #, который может быть более идиоматическим, - это использовать функцию sprintf
для объединения двух символов (Credit: @rmunn):
let a = 'a'
let b = 'b'
let s = sprintf "%c%c" a b
printfn "%O" s
// Prints "ab"
(См. https://dotnetfiddle.net/Pp9Tee)
Тем не менее, предупреждение об этом методе заключается в том, что он почти наверняка будет намного медленнее, чем любой из трех других методов, перечисленных выше.Это потому, что вместо обработки массива или String
данных напрямую, sprintf
будет выполнять более продвинутую логику форматирования для вывода. (Я не в состоянии, где я мог бы в данный момент тестировать это сам, но подключенв приведенный ниже код @ TomasPetricek для бенчмаркинга, я не удивлюсь, если вы достигнете производительности в 10 раз или более.Конечный пользователь может заметить, но будьте осторожны, если это будет использоваться в любом критичном для производительности коде.