0

I am attempting to insert a string into a StringBuilder but I get a runtime error:

Exception of type 'System.OutOfMemoryException' was thrown.

Why is this happening and how can I fix this?

My code:

Branch curBranch("properties", "");
foreach (string line in fileContents) 
{
    if (isKeyValuePair(line))
       curBranch.Value += line + "\r\n"; // Exception of type 'System.OutOfMemoryException' was thrown.
}

Implementation of Branch

public class Branch {
    private string                      key         = null;
    public StringBuilder                _value      = new StringBuilder(); // MUCH MORE EFFICIENT to append to. If you append to a string in C# you'll be waiting decades LITERALLY
    private Dictionary <string, Branch> children    = new Dictionary <string, Branch>();

    public Branch(string nKey, string nValue) {
        key     = nKey;
        _value.Append(nValue);
    }

    public string Key {
        get { return key; }
    }

    public string Value {
        get 
        { 
            return this._value.ToString(); 
        }   
        set 
        {
            this._value.Append(value);
        }
    }
}
sazr
  • 24,984
  • 66
  • 194
  • 362
  • You are basically appending an entire copy of what you have in the stringbuilder with each call of curBranch.Value += line + "\r\n"; I don't think this is doing what you want it to do. – BlakeH Jul 08 '14 at 03:19

2 Answers2

5

This line returns the entire StringBuilder contents:

return this._value.ToString();

And then you add a string to the end of the entire previous contents:

curBranch.Value += line + "\r\n";

And append it here:

this._value.Append(value);

Your StringBuilder is going to get huge very quickly, because every time you call the "setter" you're placing a copy of the entire contents into it again.


What you might consider instead is exposing the StringBuilder via your property:

public StringBuilder Value
{
    get { return this._value; }   
}

Then just use it like this:

curBranch.Value.AppendLine(line);
Grant Winney
  • 65,241
  • 13
  • 115
  • 165
  • thanks for the answer. Yes that solution would work. I was hoping for a more elegant solution that will allow the `+=` operator. Any ideas how I could maintain using this operator but only concatenate the line (not the whole StringBuilder string and line)? – sazr Jul 08 '14 at 03:24
  • 1
    @JakeM You can always redefine the "+" operator. This would allow you to do what you want. Here is an example of how to proceed : http://msdn.microsoft.com/en-us/library/6fbs5e2h.aspx. However, I do recommend you use the `AppendLine` method as its meaning is not ambiguous and could hardly be more clear. – gretro Jul 08 '14 at 03:37
2
StringBuilder sb = new StringBuilder();
foreach (string line in fileContents) 
{
    if (isKeyValuePair(line))
       sb.AppendLine(line); // Exception of type 'System.OutOfMemoryException' was thrown.
}

Try the above

I also found this explenation for why += isn't there for StringBuilder:

Why didn't microsoft overload the += operator for stringbuilder?

Community
  • 1
  • 1
TGH
  • 38,769
  • 12
  • 102
  • 135