我已经知道在 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#内存地址和变量的重复,因为我想知道如何获取引用类型的地址,并且显然该线程只处理值类型。
如果您想检查是否创建了新实例,只需将其与先前的实例进行比较即可:
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?");
}
您会发现这不会打印任何内容。
您可以使用 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;
您可以将字符串复制到另一个变量中,并比较修改前后它们的引用和值:
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));
}
将“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)}");
}
}