110,566
社区成员
发帖
与我相关
我的任务
分享
ReferenceEqual("a"+"b"+"", "ab") //返回true
ReferenceEqual("a"+""+"b", "ab") //返回false
ReferenceEqual($"ab{string.Empty}", "ab") //返回false
为什么第一个返回我是true 后面2句返回的是false?static readonly int[] A = new int[] { 1,2,3 };
虽说这个A无法被修改 但是这个数组中每一项的值还是可以用 A[1]=4;这样的方式修改 那我想让其中的任何一项在第一次赋值后都不能再被修改 可以做到吗?
// The Empty constant holds the empty string value. It is initialized by the EE during startup.
// It is treated as intrinsic by the JIT as so the static constructor would never run.
// Leaving it uninitialized would confuse debuggers.
//
//We need to call the String constructor so that the compiler doesn't mark this as a literal.
//Marking this as a literal would mean that it doesn't show up as a field which we can access
//from native.
public static readonly String Empty;
这个注释挺有意思。也指出了你需要调用 string 的构造函数才能避开编译器的优化。不过这在实际项目中没用:
new string(new char[] { 'a' });
var x = "哈哈";
那么这时候既可能让 x 引用一个独一无二的字符串对象,也可能让 x 与另外一个变量 z 应用相同的字符串对象。
所以一般来说,不要拿 c 语言底层知识直接硬套到各种高级的编程语言。高级语言也许没有 c、汇编语言那么“高”的底层执行效率,但是一定是因为有了更加复杂宏伟的目标和巨大的编程框架所以才会产生比c、汇编高级好几个数量级的语言。string.ReferenceEquals(("a" + "b" + " ").Substring(0,2), "ab");
这结果就是 false,而不是 true。这是字符串机制的特性。当你写string x = y;
的时候,字符串变量看似是引用的,然后字符串类型是一种非常特别的引用类型,它的运行时特征趋势类似于值类型,也就是在你接下来执行y=z;
的时候,这时候并不会让x 改变,而是x仍然引用原来的字符串对象,而 y 引用新的字符串对象。这个结果就好像是值类型变量赋值时总是引用所产生新的副本而并非修改引用。
当刚刚开始使用一个字符串资源时就会显现 string 原本的引用类型的特性,但是当一个 string 进行了赋值运算而必须看上去有兼容传统编程语言(例如vb1~vb6)的那种类似值类型的copy特性时则它会产生新的副本。
因此,看上去同样是值为"ab"的字符串,它既可能与另外一个值为"ab“的字符串有相同引用、有可能有完全不同的引用,这是 string 机制的复杂性决定的。你对一个字符串稍加运算,就发现字符串运算背后的代价非常巨大。所以尽量避免过多使用字符串运算功能。
struct element
{
public readonly int ele;
public element(int input)
{
ele = input;
}
}
static readonly int[] A = new int[] { 1, 2, 3 };
private void button1_Click(object sender, EventArgs e)
{
element[] arrEle = new element[3] { new element(1), new element(2), new element(3) };
foreach(element e1 in arrEle)
{
MessageBox.Show(e1.ele.ToString());
}
//arrEle[0].ele = 100; //修改时会出错
//A = new int[1]; //试图修改数组的引用A时,会出错
}
MessageBox.Show(ReferenceEquals("a"+"b"+"", "ab").ToString());
MessageBox.Show(ReferenceEquals("a"+""+"b", "ab").ToString());
MessageBox.Show(ReferenceEquals("ab"+string.Empty,"ab").ToString());
IReadOnlyList<int> list = new List<int>() { 1, 2, 3 };
Console.WriteLine(ReferenceEquals(string.Empty + "a" + "b", "ab")); // true
Console.WriteLine(ReferenceEquals("a" + "" + "b", "ab")); ; // true
Console.WriteLine(ReferenceEquals("a" + string.Empty + "b", "ab")); ; // false
Console.WriteLine(ReferenceEquals($"{string.Empty}ab", "ab")); ; // false
这里特别说明一下 前2句代码如果你是在调试模式下在即时窗口中运行 结果也都是false 不过到这里我基本上也明白为什么了 编译器优化能力还有待加强