【发布时间】:2019-12-27 10:25:14
【问题描述】:
当我执行这段代码时
class Program
{
static void Main(string[] args)
{
//scope 1
{
string x = "shark";
string y = x.Substring(0);
unsafe
{
fixed (char* c = y)
{
c[4] = 'p';
}
}
Console.WriteLine(x);
}
//scope 2
{
string x = "shark";
//Why output in this line "sharp" and not "shark" ?
Console.WriteLine(x);
}
}
}
输出是:
sharp
sharp
当我在这样的方法中分离这两个范围时:
class Program
{
static void Main(string[] args)
{
func1();
func2();
}
private static void func2()
{
{
string x = "shark";
Console.WriteLine(x);
}
}
private static void func1()
{
{
string x = "shark";
string y = x.Substring(0);
unsafe
{
fixed (char* c = y)
{
c[4] = 'p';
}
}
Console.WriteLine(x);
}
}
}
输出是:
sharp
shark
已编辑
我也这样尝试:
class Program
{
static void Main(string[] args)
{
{
string x = "shark";
string y = x.Substring(0);
unsafe
{
fixed (char* c = y)
{
c[4] = 'p';
}
}
Console.WriteLine(x);
}
void Test(){
{
string x = "shark";
Console.WriteLine(x);
}
}
Test();
}
}
输出是:
sharp
shark
**我使用的环境是 MacOS 和 .net core 2.2 (Rider) **
我希望在所有情况下都有相同的输出,但输出不同。正如我们所知,实习是您硬编码的所有字符串都被放入汇编中并在整个应用程序中全局重用,以重用相同的内存空间。但在这段代码的情况下,我们看到
硬编码字符串只能在函数范围内重用,而不是在全局范围内。
这是 .NET Core 错误还是有解释?
【问题讨论】:
-
除此之外,字符串是不可变的,因此您违反了不直接修改字符串内存的长期约定。如果您需要以这种方式修改字符串,请使用
StringBuilder。 -
当您使用
unsafe访问实现定义的详细信息时,为什么会是一个“错误”?你是什么字符串类的内部优化,但没有什么是违反任何合同的。 -
“我希望……” 尝试在 C# 或 .NET 规范中找到符合该期望的子句。
-
.NET Core bug这绝对不是错误。您正在做一些明确标记为unsafe的事情。然后经历了对您来说意外的行为,因为实习(这是一个实施细节)没有按照您期望的方式行事。未定义的行为是未定义的——规范中没有任何内容说代码不能按照它的行为方式行事。所以绝对不是bug。充其量是奇怪 - 但不是错误。 -
@hovjan:我很想深入研究它,因为我自己还没有看到这种行为,而且我喜欢这种深入的东西。但是,我认为您在这里忽略了要点,那就是您不应该修改字符串。故事结束。