如何在C#中证明字符串的不变性?

Bin*_*Sam 10 c# string immutability

在我上次的c#访谈中,
我被要求证明C#字符串的不变性,我知道c#字符串的不变性意味着什么,但是有可能通过代码证明c#字符串的不变性吗?请问我有一个示例代码片段吗?提前致谢

Mat*_*son 9

我能证明string不是一成不变的.我需要做的就是显示一些变异的代码string,如下所示:

using System;
using System.Runtime.InteropServices;

namespace Demo
{
    class Program
    {
        static void Main(string[] args)
        {
            const string test = "ABCDEF"; // Strings are immutable, right?
            char[] chars = new StringToChar {str = test}.chr;
            chars[0] = 'X';

            // On an x32 release or debug build or on an x64 debug build, 
            // the following prints "XBCDEF".
            // On an x64 release build, it prints "ABXDEF".
            // In both cases, we have changed the contents of 'test' without using
            // any 'unsafe' code...

            Console.WriteLine(test);

            // The following line is even more disturbing, since the constant
            // string "ABCDEF" has been mutated too (because the interned 'constant' string was mutated).

            Console.WriteLine("ABCDEF");
        }
    }

    [StructLayout(LayoutKind.Explicit)]
    public struct StringToChar
    {
        [FieldOffset(0)] public string str;
        [FieldOffset(0)] public char[] chr;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在是否应该将其视为C#中的错误是另一回事.:)(答案可能FieldOffset应该被认为是unsafe- 上面的代码据称是safe,因此不string应该是可变的.)

此外,我认为你可以合理地认为这string在精神上是不可改变的,即使有一些愚蠢的边缘案例违反了它在所谓的安全代码中的不变性.

  • @samurai我认为你可能需要更仔细地考虑情况的逻辑.字符串不能同时是不可变的和可变的.由于前者是否定的证明,后者立即使任何假定的证据无效."如何证明c#字符串是不可变的"问题的答案是你*不能*因为它们不是不可变的.仅仅因为他们没有变异*在某些情况下*不能证明他们*不能变异*. (2认同)
  • @Sylverac也尝试使用我最新编辑的代码,我添加了`Console.WriteLine("ABCDEF");` - 甚至不打印"ABCDEF"了! (2认同)
  • @Sylverac不,这根本不一样.编译器在连接它们时不是直接创建新的字符串 - 它是`String`中的连接方法的实现,它实现了这一点(参见[ReferenceSource]中的实现)(http://referencesource.microsoft .COM /#mscorlib程序/系统/ string.cs,17e1cc2f91f20974,引用)).这些创建并返回对新字符串的引用.还要注意,`str + ="XXX"`字符串连接变成了对`str = string.Concat(str,"XXX")`的调用.为`+ =`创建了新的字符串,但是我的代码不会创建它们. (2认同)
  • @Sylverac会发生什么:首先创建一个`StringToChar`结构的实例,引用分配给结构的`str`字段的字符串`test`(注意:分配了引用,而不是字符串的副本) .然后结构中的`chr`字段用于访问字符串的内容,就好像它是一个字符数组(即提供对字符串内容的直接访问).它通过使用`FieldOffset(0)`来使结构像C++联合一样.最后,代码更改了char数组的第一个元素(更改了底层字符串). (2认同)