【问题标题】:Why is modifying this String also modifying the content of another, seperate String?为什么修改此字符串也会修改另一个单独字符串的内容?
【发布时间】:2020-08-06 08:44:48
【问题描述】:

在我的静态 main 函数中,我有以下代码:

string str1 = "aaaaaaaaa";
pointerTest();
Console.WriteLine( "str1 is: " + str1 );

声明为unsafe的静态pointerTest-方法包含以下内容:

string str2 = "aaaaaaaaa";
fixed( char* ptr = str2 )
{
    for( int i = 0; i < str2.Length / 3; ++i )
        ptr[i] = 'z';
}

Console.WriteLine( "str2 is: " + str2 );

请注意str1str2 是如何独立声明的,但内容相同。

这个程序的预期输出是:

str2 is: zzzaaaaaa
str1 is: aaaaaaaaa

当我运行程序时,实际输出会显示:

str2 is: zzzaaaaaa
str1 is: zzzaaaaaa

当我将str2str1 更改为不具有完全相同的内容时(例如,在str2 的末尾再添加一个“a”),程序会像预期的那样运行。
如果发现这种行为在 .Net Core 3.1Mono 中都存在(不确定确切的版本,我使用了Repl.It

我的问题是为什么会发生这种行为以及如何解决它。

【问题讨论】:

    标签: c# string pointers reference compiler-optimization


    【解决方案1】:

    我的理论是,这是由于编译器优化,特别是一个称为字符串实习的过程:

    编译器认识到没有必要自己分配str2,因为内存中已经有完全相同的字符序列,是在str1的初始化时分配的。因此,它不是重新分配它,而是使str2 成为对str1 已经指向的位置的引用。更多相关信息可以阅读here

    字符串在 C# 中被认为是不可变的,因此 - 在正常情况下 - 不应以任何方式、形状或形式修改其内容。

    由于此代码使用unsafe 关键字和指针逻辑,因此不能保证不会导致未定义的行为,这会导致令人惊讶的结果。

    解决这个“问题”的唯一方法是遵守 C# 的规范并将 Strings 视为不可变的。

    【讨论】:

    • 我不知道,感谢您的输入。我编辑了答案以添加术语和您共享的网站的链接。
    猜你喜欢
    • 2021-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-12
    • 2014-05-30
    • 2020-09-02
    • 2014-10-07
    相关资源
    最近更新 更多