Bab*_*boB 19 .net c# string equality string-interning
我在网站上找到了如下代码.
string a = "xx";
string b = "xx";
string c = "x";
string d = String.Intern(c + c);
Console.WriteLine((object)a == (object)b); // True
Console.WriteLine((object)a == (object)d); // True
Run Code Online (Sandbox Code Playgroud)
在这里,再次投射到对象类型的目的是什么,因为a,b,d本身就是字符串的对象?
Ham*_*jam 24
C#编译器将尝试在编译时获取所有常量字符串.这称为字符串实习.所以在生成代码之后a
,b
它们是对包含"xx" 的相同字符串的引用.
您可以通过比较它们的引用(将它们转换为对象并进行相等性检查或使用object.ReferenceEquals
)来检查这一点.请记住,==
字符串运算符比较它们的值而不是它们的引用.
string a = "xx";
string b = "x" + "x"; // String interning here
string c = string.Join("", new[] { "x", "x" }); // No interning here because it is evaluated at runtime
Console.WriteLine((object)a == (object)b); // True. Reference check
Console.WriteLine(a == b); // True. Value check
Console.WriteLine((object)a == c); //False. Reference check. Described below
Console.WriteLine(a == c); // True. Value check
Run Code Online (Sandbox Code Playgroud)
那么为什么Console.WriteLine((object)a == c);
要做参考检查?因为编译器会==
在对象上选择运算符来检查引用相等性.
因此,在您的问题中投射到对象的重点是检查字符串实习是否有效.假设编译时没有实习.
string a = "xx";
string b = "xx";
string c = "x";
string d = String.Intern(c + c);
Run Code Online (Sandbox Code Playgroud)
然后Console.WriteLine((object)a == (object)b);
将打印"False",因为a
并且b
是内存中两个不同字符串的引用,两者都看起来像"xx".
对提供的答案的补充: 字符串(C#参考)
的System.String类是不可变的引用类型在.NET框架类库提供.此类在内部为任何字符串操作操作创建新的字符串对象.虽然语法使得它看起来好像可以更改内容,但此类对象的内容不会更改.此外,字符串用作哈希表键以计算哈希值,以避免破坏哈希数据结构的风险.
例:
string a = "hello";
string b = "h";
// Append to contents of 'b'
b += "ello";
// When you set the variable's b value to "hello",
// this would result in changing the pointer
// to the object in the HEAP the variable "a" is already pointing to
// Result would be: (reference of a == reference of b) --> TRUE
// b = "hello";
Console.WriteLine(a == b); // value comparison
Console.WriteLine((object)a == (object)b); // reference comparison
Console.WriteLine (object.ReferenceEquals(a,b)); // reference comparison without casting
Run Code Online (Sandbox Code Playgroud)
结果:
True
False
False
Run Code Online (Sandbox Code Playgroud)
说明:
这将创建一个新对象:
string a = "hello";
Run Code Online (Sandbox Code Playgroud)
这将创建另一个对象:
string b = "h";
Run Code Online (Sandbox Code Playgroud)
这将创建另一个对象:
b += "ello";
Run Code Online (Sandbox Code Playgroud)
下面将创建对现有对象的引用,更准确地说,它将指向变量"a"指向→"hello"的同一对象.
string c = "hello";
Console.WriteLine (object.ReferenceEquals(a,c)); // --> TRUE
Run Code Online (Sandbox Code Playgroud)
字符串是不可变的 - 创建对象后,字符串对象的内容无法更改,尽管语法使其看起来好像可以执行此操作.例如,当您编写此代码时,编译器实际上会创建一个新的字符串对象来保存新的字符序列,并将该新对象分配给b.然后字符串"h"有资格进行垃圾回收.
C#使用==
令牌来表示三个不同的运算符:一个可重载的相等检查运算符(如果对于所讨论的确切类型存在重载,则可用于类类型或值类型),一个不可重载的引用标识检查运算符(这需要两者都有)操作数是类引用,并要求类型不是互斥的),以及一个空检查操作符(可用于任何类类型,可空值类型或可能是上述之一的泛型).虽然大多数形式的重载是在.NET语言中以统一的方式定义的,但是对于所有这三种相等使用一个运算符则不然.像VB.NET其它语言使用不同的令牌针对第一形式(例如在VB.NET,表达(x = y)
使用如果定义一个相等测试过载,或生成语法错误若否; (x Is y)
测试是否x
与y
识别相同的对象实例不考虑是否存在重载的相等运算符).
强制转换的目的Object
是确保==
令牌被解释为表示reference-identity-check运算符而不是可重载的等于运算符; 这样的强制转换只是因为C实现了==
运算符,而在VB.NET等其他语言中是不需要的.
归档时间: |
|
查看次数: |
734 次 |
最近记录: |