I am not sure why it changes when you change it from 10 to 1
I believe this is an implementation detail and you should not rely on it (will try to find something in the specs) but some positive single digit numbers are cached in int.ToString
implementation for .NET Core. Here is excerpt from UInt32ToDecStr
which is called internally by int.ToString
:
// For single-digit values that are very common, especially 0 and 1, just return cached strings.
if (bufferLength == 1)
{
return s_singleDigitStringCache[value];
}
As for equality - please check:
- C# difference between == and Equals().
- String interning in .Net Framework. (compiler will intern string literals, so all of them will point to the same address in memory)
- Using type dynamic
UPD:
Was not able to find anything in specs, but next code behaves differently in .NET Framework and .NET 6 (former one prints 11 times False
and the latter prints 10 times True
and one False
):
var dict = new Dictionary<int, string>()
{
{0, "0"},
{1, "1"},
{2, "2"},
{3, "3"},
{4, "4"},
{5, "5"},
{6, "6"},
{7, "7"},
{8, "8"},
{9, "9"},
{10, "10"},
};
foreach(var kvp in dict)
{
Console.WriteLine(object.ReferenceEquals(kvp.Key.ToString(), kvp.Value));
}
UPD2:
The caching was introduced for performance reasons by this PR and is mentioned in Performance Improvements in .NET Core 3.0 blogpost:
In some sizeable web applications, we found that a large number of strings on the managed heap were simple integral values like “0” and “1”. And since the fastest code is code you don’t need to execute at all, why bother allocating and formatting these small numbers over and over when we can instead just cache and reuse the results (effectively our own string interning pool)? That’s what PR dotnet/coreclr#18383 does, creating a small, specialized cache of the strings for “0” through “9”, and any time we now find ourselves formatting a single-digit integer primitive, we instead just grab the relevant string from this cache.
private int _digit = 4;
[Benchmark]
public string SingleDigitToString() => _digit.ToString();
Method |
Toolchain |
Mean |
Error |
StdDev |
Ratio |
Gen 0 |
Gen 1 |
Gen 2 |
Allocated |
SingleDigitToString |
netcoreapp2.1 |
17.72 ns |
0.3273 ns |
0.3061 ns |
1.00 |
0.0152 |
– |
– |
32 B |
SingleDigitToString |
netcoreapp3.0 |
11.57 ns |
0.1750 ns |
0.1551 ns |
0.65 |
– |
– |
– |
– |