В чём может быть опасность изменения строк? (Пример кода)

Рейтинг: 0Ответов: 0Опубликовано: 14.08.2023

Сделал пример кода, меняющего содержимого строки в памяти.

void Main()
{
    GC.Collect();
    string s1 = "abcdef";
    string s2 = null;
    s2 = "abc";
    s2 += "def";
    string s3 = "abcdef";
    $"s1: {s1}".Dump();
    $"s2: {s2}".Dump();
    $"s3: {s3}".Dump();
    GC.Collect();
    //
    "".Dump();
    HackedString str1 = new() { STRING = s1 };
    HackedString str2 = new() { STRING = s2 };
    HackedString str3 = new() { STRING = s3 };
    //
    str3.SetChar(0, 'A');
    str3.SetChar(5, 'U');
    $"s1: {s1}".Dump();
    $"s2: {s2}".Dump();
    $"s3: {s3}".Dump();
}

unsafe ref struct HackedString
{
    public string STRING { get; set; }
    private void* _pointer(string _string) => (void*)*(nint*)(nint)(&_string);
    public char GetChar(nint char_position)
    {
        void* p = _pointer(STRING);
        long offset = 4 + char_position;
        char* ch = (char*)p + offset;
        return *ch;
    }
    public void SetChar(nint char_position, char new_char)
    {
        void* p = _pointer(STRING);
        long offset = 4 + char_position;
        char* ch = (char*)p + offset;
        *ch = new_char;
    }
    public override string ToString() => STRING;
}

Вывод:

s1: abcdef
s2: abcdef
s3: abcdef

s1: AbcdeU
s2: abcdef
s3: AbcdeU

Как видно, строки s1 и s2 имеют одно и то же содержимое. Начитавшись "умных" статей, в которых писалось, что строки экономят память, и если содержимое совпадает - то под капотом одна и та же ссылка. Но по экспериментам это оказалось не так. Даже запрос к сборщику мусора (с надеждой что он найдёт дубликат) не дал эффекта. Изначально записанные строки s1 и s3 содержать под капотом одну и ту же ссылку на char[], но строка s2, которая только потом стала походить на s1 и s3 имеет другой char[], хоть и с идентичным содержимым.

Выходит, что экономия происходит только на этапе компиляции?
И уже созданные после запуска программы строки можно менять без опасения?

Ответы

Ответов пока нет.