Почему при выполнении теста в приведенном ниже коде не отображается выделение памяти для метода BuildString
? Я этого не понимаю, потому что, насколько я знаю, строка должна располагаться в куче.
[MemoryDiagnoser]
public class StringBenchmark
{
[Benchmark]
public string BuildString()
{
return "Test";
}
[Benchmark]
public string BuildStringUsingStringConcatenationMethod()
{
return string.Concat("Hello", 2022, "/", 5);
}
}
Результаты тестов:
Компилятор может использовать «внутренние» строки для литералов, т. е. каждый раз, когда вы используете "abc"
в своем коде, он может использовать один и тот же экземпляр "abc"
. Сюда входят выражения, которые компилятор может оценивать как константы во время сборки, например объединение других константных выражений.
Вы можете проверить это:
using System;
string a = Strings.Fixed(), b = Strings.Fixed(),
c = Strings.New(), d = Strings.New();
// writes "abc; equal? True; same? True"
Console.WriteLine($"{a}; equal? {string.Equals(a,b)}; same? {ReferenceEquals(a,b)}");
// writes "def; equal? True; same? False"
Console.WriteLine($"{c}; equal? {string.Equals(c,d)}; same? {ReferenceEquals(c,d)}");
static class Strings
{
// returns interned instance
public static string Fixed() => "abc";
// creates a new instance each time
public static string New() => new string("def".AsSpan());
}
Память для константных строк обычно выделяется во время инициализации приложения. Поскольку строки неизменяемы, они остаются неизменными, что устраняет необходимость в дополнительном выделении памяти при каждом вызове метода. Это похоже на возврат «указателя».