“证明”字符串在c#中是不可变的

问题描述 投票:0回答:4

我已经知道在 C# 中,字符串是引用类型,主要像值类型一样处理,但我最近发现了这一点: http://net-informations.com/faq/general/immutable.htm

我试图通过在发生连接时打印对字符串变量的引用来“证明”字符串是不可变的:

string s = string.Empty;
for (int i = 0; i < 10; i++)
{
    s += " " + i;
    // Console.WriteLine(&s);
}

正如您所猜测的,如果该行未注释,则代码不会编译(编译器错误 CS0208:无法获取托管类型的地址、大小或声明指向托管类型('type')的指针)。

我也尝试了 GetHashCode(),但显然对于字符串,它根据...字符串值本身返回相同的值(即,例如,它总是为“0”返回相同的结果)。

有办法做到这一点吗?它不会用于编码目的,只是为了理解目的......如果不是,你怎么知道它会在每次串联时“真正”创建 n 个字符串实例?除了“知道”之外...

编辑:可能不是C#内存地址和变量的重复,因为我想知道如何获取引用类型的地址,并且显然该线程只处理值类型。

c# string immutability
4个回答
2
投票

如果您想检查是否创建了新实例,只需将其与先前的实例进行比较即可:

string s = string.Empty;
for (int i = 0; i < 10; i++)
{
    var saved = s;
    s += " " + i;
    if (ReferenceEquals(saved, s))
        Console.WriteLine("oops, no new instance created?");
}

您会发现这不会打印任何内容。


2
投票

您可以使用 ObjectIDGenerator 为字符串生成 id,并查看 id 是否相同。

var string1 = "Jerry";
ObjectIDGenerator generator = new ObjectIDGenerator();
bool string1FirstTime;
long string1Id = generator.GetId(string1, out string1FirstTime);


bool string2FirstTime;
var string2 = string1 + " Seinfeld";
long string2Id = generator.GetId(string2, out string2FirstTime);

下面会返回 false,因为它们不一样。

var same = string1Id == string2Id;

1
投票

您可以将字符串复制到另一个变量中,并比较修改前后它们的引用和值:

string s = string.Empty;
for (int i = 0; i < 10; i++)
{
    var copy = s;

    // true
    Console.WriteLine("both are the same reference: {0}", Object.ReferenceEquals(s, copy));
    // true
    Console.WriteLine("both are the same value: {0}", s.Equals(copy));

    s += " " + i;

    // false
    Console.WriteLine("both are the same reference: {0}", Object.ReferenceEquals(s, copy));
    // false
    Console.WriteLine("both are the same value: {0}", s.Equals(copy));
}

0
投票

将“String”和“StringBuilder”组合在一个类中

class ProveStringIsImmutable
{

    //this method proves that string is Immutable (when its change - always new memory will be created)
    public static void ChangeString(string strInput)
    {
        var orgString = strInput;

        Console.WriteLine("strInput before change: " + orgString);

        Console.WriteLine($"ReferenceEquals(orgString, strInput) = {ReferenceEquals(orgString, strInput)}");

        strInput = strInput + " 123";

        Console.WriteLine("strInput after change: "+ strInput);

        Console.WriteLine($"ReferenceEquals(orgString, strInput) = {ReferenceEquals(orgString, strInput)}");
    }

    //this method proves that StringBuilder is Mutable (when its change - no new memory will be created)
    public static void ChangeString(StringBuilder sbInput)
    {
        var orgString = sbInput;

        Console.WriteLine("strInput before change: " + orgString);

        Console.WriteLine($"ReferenceEquals(orgString, strInput) = {ReferenceEquals(orgString, sbInput)}");

        sbInput = sbInput.Append( " 123");

        Console.WriteLine("strInput after change: " + sbInput);

        Console.WriteLine($"ReferenceEquals(orgString, strInput) = {ReferenceEquals(orgString, sbInput)}");
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.