Published on
- 1 min read
StringBuilder tip: use Append without ToString

This is a new part of a series where I analyze .NET code quality rules from a performance perspective. Today, let’s talk about CA1830: Prefer strongly-typed Append and Insert method overloads on StringBuilder.
Rule description
This rule suggest us not to convert parameters to string when using Append
or Insert
methods:
var i = 123;
var sb = new StringBuilder();
sb.Append(i.ToString()); // CA1830
Instead, pass the value directly:
var i = 123;
var sb = new StringBuilder();
sb.Append(i);
This rule applies to well-known primitive types like byte
, short
, int
, double
, long
, and so on.
Performance analysis
I wrote a simple benchmark to see how much these approaches really affect performance. The results are in the repo and on the diagram below.

Performance comparison chart
There’s a small time difference between these two approaches — about 5 microseconds on my laptop. The memory difference is more significant — about 20 KiB.
How the optimization works?
When you use a strongly-typed overload like Append(int), .NET internally calls methods like: AppendSpanFormattable<T>
and InsertSpanFormattable<T>
.
Here’s a simplified version of AppendSpanFormattable<T>
:
private StringBuilder AppendSpanFormattable<T>(T value) where T : ISpanFormattable
{
if (value.TryFormat(RemainingCurrentChunk, out int charsWritten, format: default, provider: null))
{
m_ChunkLength += charsWritten;
return this;
}
return Append(value.ToString());
}
This method uses ISpanFormattable.TryFormat
to write the value directly into the internal buffer as a Span<char>
. This avoids: allocating a temporary string, boxing value types, calling the virtual ToString()
method.
Should you care?
Yes, you probably should. Even if we don’t care about performance benefits, this code:
sb.Append(i);
…is cleaner and simpler than:
sb.Append(i.ToString());
And as a bonus — it’s faster and allocates less memory. Win-win.