Question

In C#, I have a StringBuilder sb to which I am appending numerous times in for-loops.

Is there is a simple method for StringBuilders that spits out the last string that was appended to it?

Was it helpful?

Solution

Nope. You should probably use a list of strings and then later join it to replace the StringBuilder functionality like this:

List<string> strings = new List<string>();
strings.Add("...");
string result = string.Join("", strings);

Then you can access the most recently added string by accessing the last index of the string list or use the Last() LINQ extension like this:

string lastString = strings.Last();

OTHER TIPS

You could create your own StringBuilder extension method that remembers the last string appended:

public static class StringBuilderExtensions
{
    public static string LastStringAppended { get; private set; }

    public static StringBuilder AppendRemember(this StringBuilder sb, object obj)
    {
        string s = obj == null ? "" : obj.ToString();
        LastStringAppended = s;
        return sb.Append(s);
    }
}

Call it like this

 sb.AppendRemember("hello").AppendRemember(" world");
 string lastString = StringBuilderExtensions.LastStringAppended;

However, note that the last string will be remembered globally. It is not bound to a StringBuilder instance.


If you need to remember the last addition per StringBuilder instance, you can attach an additional "property" to the StringBuilder via a dictionary. I am using this implementation of ObjectReferenceEqualityComparer<T>. It is necessary beacuse StringBuilder overrides Equals and does not use reference equality.

public static class StringBuilderExtensions
{
    private static Dictionary<StringBuilder, string> _lastStrings =
        new Dictionary<StringBuilder, string>(
            new ObjectReferenceEqualityComparer<StringBuilder>());

    public static string LastAppended(this StringBuilder sb)
    {
        string s;
        _lastStrings.TryGetValue(sb, out s);
        return s; // s is null if not found in the dict.
    }

    public static StringBuilder AppendRemember(this StringBuilder sb, object obj)
    {
        string s = obj == null ? "" : obj.ToString();
        _lastStrings[sb] = s;
        return sb.Append(s);
    }
}

Use it like this:

sb.AppendRemember("hello").AppendRemember(" world");
string lastString = sb.LastAppended();

As floele answered, you're probably better off just using a List and then joining it. But as Olivier Jacot-Descombes and Tim Schmelter hinted at in their commeents, you can have your own class with an internal StringBuilder, then you just have to recreate the methods from StringBuilder you want to use, and store the last appended string inside your class in a property. This has two key advantages over Olivier's answer: the remembered string isn't "global" (it's unique to each instance), and the code is many times simpler.

public class StringBuilderRemember
{
    private StringBuilder sb=new StringBuilder();
    public string LastString {get; private set;}

    public void AppendLine(string s)
    {
        LastString=s;
        sb.AppendLine(s);
    }
    public void Append(string s)
    {
        LastString=s;
        sb.Append(s);
    }
    public string ToString()
    {
    return sb.ToString();
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top