Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何证明C#中字符串的不可变性?_C#_String_Immutability - Fatal编程技术网

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

如何证明C#中字符串的不可变性?,c#,string,immutability,C#,String,Immutability,在我上次的c#采访中,我被要求证明c#string的不变性,我知道什么是c#string的不变性,但有可能通过代码证明c#string的不变性吗?请给我一个示例代码片段。 提前感谢是的,可以使用ObjectiveGenerator类来证明c#字符串的不变性。 下面的答案摘自dotmob在C#中的一篇文章 实际上,ObjutDebug将为我们在程序中创建的实例返回一个唯一的整数值。在这个类的帮助下,我们可以检查是否为String和String BuueLead中的各种操作创建了新的实例。 usin

在我上次的c#采访中,
我被要求证明c#string的不变性,我知道什么是c#string的不变性,但有可能通过代码证明c#string的不变性吗?请给我一个示例代码片段。
提前感谢

是的,可以使用
ObjectiveGenerator
类来证明c#字符串的不变性。

下面的答案摘自dotmob在C#中的一篇文章

实际上,ObjutDebug将为我们在程序中创建的实例返回一个唯一的整数值。在这个类的帮助下,我们可以检查是否为String和String BuueLead中的各种操作创建了新的实例。

using System;
using System.Text;
using System.Runtime.Serialization;

class Program
{
  static void Main(string[] args)
  {
    ObjectIDGenerator idGenerator = new ObjectIDGenerator();
    bool blStatus = new bool();
    //just ignore this blStatus Now.
    String str = "My first string was ";
    Console.WriteLine("str = {0}", str);
    Console.WriteLine("Instance Id : {0}", idGenerator.GetId(str, out blStatus));
    //here blStatus get True for new instace otherwise it will be false
    Console.WriteLine("this instance is new : {0}\n", blStatus);
    str += "Hello World";
    Console.WriteLine("str = {0}", str);
    Console.WriteLine("Instance Id : {0}", idGenerator.GetId(str, out blStatus));
    Console.WriteLine("this instance is new : {0}\n", blStatus);
    //Now str="My first string was Hello World"
    StringBuilder sbr = new StringBuilder("My Favourate Programming Font is ");
    Console.WriteLine("sbr = {0}", sbr);
    Console.WriteLine("Instance Id : {0}", idGenerator.GetId(sbr, out blStatus));
    Console.WriteLine("this instance is new : {0}\n", blStatus);
    sbr.Append("Inconsolata");
    Console.WriteLine("sbr = {0}", sbr);
    Console.WriteLine("Instance Id : {0}", idGenerator.GetId(sbr, out blStatus));
    Console.WriteLine("this instance is new : {0}\n", blStatus);
    //Now sbr="My Favourate Programming Font is Inconsolata"
    Console.ReadKey();
  }
}
输出将如下所示

当str与“Hello World”连接时,字符串的实例id从1更改为2。而sbr的实例id在追加操作后也保持与3相同。这说明了所有关于可变性和不变性的问题。blStatus变量指示实例是否为新实例


您可以在以下位置找到关于该主题的完整文章:

我可以证明
字符串
不是不变的。我所需要做的就是显示一些变异
字符串的代码,如下所示:

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;
    }
}
现在,这是否应该被视为C#中的错误是另一回事 (答案可能是
FieldOffset
应该被认为是
不安全的
——上面的代码据称是
安全的
,因此
字符串
不应该是可变异的。)


此外,我认为您可以合理地争辩说,
string
在精神上是不可变的,即使在假定安全的代码中存在违反其不可变性的愚蠢边缘情况。

检查两个string对象的对象引用,它们是一样的。写一个连接字符串的循环,然后看着GC发疯,你的应用程序像发疯一样耗尽内存?你不能——事实上你可以证明你可以使用不安全的代码来改变字符串。您所能做的最好的事情就是指向承诺字符串是不可变的规范(在CLR安全代码的上下文中)。如果你的工作是编程,你必须习惯于相信语言规范——如果语言没有按照规范所说的去做,那么编译器团队就要修复它。您可以演示一个示例,其中字符串没有变异,但它不能证明任何东西。可能存在这样失败的构造。在你找到一个之前,你必须相信规范。他们可能只是想听听你如何处理问题,你的想法,讨论等等。并不是真的希望你证明字符串是不可变的。否则,这就是一个不太好的面试问题:)@M.kazemAkhgary是的,但这可以在C#本身的范围内完成。这不像我们在使用调试器、反汇编程序、代码注入或其他任何东西——只是完全有效的C代码。如果面试官想要一个更具体的答案,他们应该问一个更连贯、更具体的问题。让我先检查一下,如果答案正确,我会接受你的回答。这只能证明你正在测试的运算符和方法创建了新的字符串实例。这并不能证明字符串总是不可变的。参见J在问题下方的评论,为什么不可能用数学/科学意义上的证明来证明。‒-1对于绝对错误的陈述
,可以证明c#string的不变性,如果您编辑您的答案以删除此断言并合并@René提供的信息,将切换到upvoteVogt@samurai我认为你可能需要更仔细地考虑形势的逻辑。字符串不能同时是不可变和可变的。由于前者是否定的证明,后者立即使任何假定的否定证明无效。“如何证明c#字符串是不可变的”这个问题的答案是,你不能,因为它们不是不可变的。仅仅因为它们在某些情况下没有变异,并不能证明它们不能变异。@samurai Simple logic,如果您可以通过显示一个可以变异的情况来直接证明
string
是可变的,这意味着它不能是不变的。@Sylverac还可以用我最新编辑的代码来尝试,我在其中添加了
Console.WriteLine(“ABCDEF”));-它甚至不再打印“ABCDEF”@Sylverac不,一点都不一样。当您连接新字符串时,编译器并不是直接自己创建新字符串,而是
String
中连接方法的实现(请查看中的实现)。它们创建并返回对新字符串的引用。还要注意的是,
str+=“XXX”
string串联转换为对
str=string.Concat(str,“XXX”)
的调用。为
+=
创建了新字符串,但我的代码没有创建它们。@Sylverac发生的事情是:首先创建
StringToChar
结构的一个实例,并将对字符串
test
的引用分配给结构的
str
字段(注意:分配的是引用,而不是字符串的副本)。然后,结构中的
chr
字段用于访问字符串的内容,就像它是一个字符数组一样(即提供对字符串内容的直接访问)。通过使用<代码>字段偏移(0)< /C> >使结构像C++联盟一样运行。最后,代码更改了char数组的第一个元素(它更改了底层字符串)。