This is a hack (It only works with reflection) to let you achieve garbage free string concatenation in C#, Mono:
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
public class StringReference
{
public int MaxSize
{
get;
private set;
}
public int SpaceLeft
{
get { return MaxSize - StringLength; }
}
public int StringLength
{
get { return StringBuilder.Length; }
}
public string StringHandle
{
get;
private set;
}
public StringBuilder StringBuilder
{
get;
private set;
}
public StringReference(int maxSize=32)
{
Resize(maxSize);
}
public void Resize(int maxSize)
{
MaxSize = maxSize;
StringBuilder = new StringBuilder(maxSize, maxSize);
var initialized = false;
try
{
// This should work in Mono (Unity3D)
var typeInfo = StringBuilder.GetType().GetField("_str", BindingFlags.NonPublic | BindingFlags.Instance);
if(typeInfo != null)
{
StringHandle = (string)typeInfo.GetValue(StringBuilder);
initialized = true;
}
}
catch
{
try
{
// This might work on a .NET platform
var typeInfo = StringBuilder.GetType().GetField("_cached_str", BindingFlags.NonPublic | BindingFlags.Instance);
if (typeInfo != null)
{
StringHandle = (string)typeInfo.GetValue(StringBuilder);
initialized = true;
}
}
catch
{
throw new Exception("Can't get access to StringBuilders internal string.");
/*
* Uncomment this section to get a clue on how to get a reference to the underlying string:
*
Type t = StringBuilder.GetType();
foreach (var f in t.GetFields(BindingFlags.NonPublic | BindingFlags.Instance))
UnityEngine.Debug.Log(f.Name);
*/
}
}
}
public void Clear()
{
StringBuilder.Remove(0, StringBuilder.Length);
}
public void SetText(string text, bool fillOverflow = true)
{
SetText(ref text, fillOverflow);
}
public void SetText(ref string text, bool fillOverflow = true)
{
Clear();
var max = SpaceLeft;
if (text.Length >= SpaceLeft)
{
StringBuilder.Append(text, 0, max);
}
else
{
StringBuilder.Append(text);
if(fillOverflow) FillOverflow();
}
}
public void Append(ref string text)
{
var max = SpaceLeft;
if (text.Length >= SpaceLeft)
StringBuilder.Append(text, 0, max);
else
StringBuilder.Append(text);
}
public void Append(string text)
{
Append(ref text);
}
public void FillOverflow(char character = ' ')
{
var overflow = SpaceLeft;
if (overflow > 0)
StringBuilder.Append(character, overflow);
}
}
How to use:
StringReference str = null;
str = new StringReference(128);
str.StringBuilder.Append("This is an example of garbage-");
str.StringBuilder.Append("free string concatenation.");
Debug.Log(str.StringHandle);