Преимущество
StringBuilder
s над string
обусловлено минимизацией распределений.Он предварительно выделяет буфер, чтобы избежать выделения для каждой вставки / добавления.Это требует изменчивости - некоторый объект должен владеть (и мутировать) буфером.
Кстати, System.String
уже соответствует (что я могу сделать) вашему описанию: он неизменен и поддерживает конкатенацию, вставка MSDN и удаление MSDN .
ОБНОВЛЕНИЕ
Идея Томаса заинтриговала меня.Взяв его идею, вот что я придумал
type StringBuilder =
private
| Empty
| StringBuilder of int * string * int * StringBuilder
member this.Length =
match this with
| Empty -> 0
| StringBuilder(_, _, n, _) -> n
override this.ToString() =
let rec rev acc = function
| Empty -> acc
| StringBuilder(idx, str, _, bldr) -> rev ((idx, str)::acc) bldr
let buf = ResizeArray(this.Length)
for idx, str in rev [] this do buf.InsertRange(idx, str)
System.String(buf.ToArray())
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
[<RequireQualifiedAccess>]
module StringBuilder =
let empty = Empty
let length (bldr:StringBuilder) = bldr.Length
let insert index str bldr =
if index < 0 || index > (length bldr) then invalidArg "index" "out of range"
StringBuilder(index, str, str.Length + bldr.Length, bldr)
let create str = insert 0 str empty
let append str bldr = insert (length bldr) str bldr
let remove index count (bldr:StringBuilder) = create <| bldr.ToString().Remove(index, count)
Использование
let bldr =
StringBuilder.create "abcdef"
|> StringBuilder.insert 1 "xyz"
|> StringBuilder.append "123"
|> StringBuilder.remove 1 2
bldr.ToString() //azbcdef123
Он постоянен и вставка O (1).