投入"对象"的目的是什么?类型?

时间:2016-07-02 09:25:22

标签: c# .net 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

这里,再次投射到对象类型的目的是什么,因为a,b,d本身就是字符串的对象?

4 个答案:

答案 0 :(得分:24)

C#编译器将尝试在编译时获取所有常量字符串。这称为字符串实习。因此,生成的代码ab 引用后,相同的字符串包含" xx"。

您可以通过比较它们的引用(将它们转换为对象并进行相等性检查或使用object.ReferenceEquals)来检查这一点。请记住,==字符串运算符会比较它们的值而不是它们的引用。

另一件需要提及的是.NET中的strings are immutable

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

那么Console.WriteLine((object)a == c);为什么要进行参考检查?因为编译器会在对象上选择==运算符来检查引用相等性。

因此,在您的问题中投射到对象的重点是检查字符串实习是否有效。 假设编译时没有实习

 string a = "xx";
 string b = "xx";
 string c = "x";
 string d = String.Intern(c + c);

然后Console.WriteLine((object)a == (object)b);将打印" False",因为ab引用两个不同的字符串在记忆中,两者都看起来像" xx"。

答案 1 :(得分:6)

对提供的答案的补充: string (C# Reference)

  

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

<强>结果:

True
False
False

<强>解释

这将创建一个新对象:

string a = "hello";

这将创建另一个对象:

string b = "h"; 

这将创建另一个对象:

b += "ello";

以下将创建对现有对象的引用,更确切地说,它将指向变量“a”指向→“hello”的同一对象。

string c = "hello"; 
Console.WriteLine (object.ReferenceEquals(a,c)); // --> TRUE
  

字符串是不可变的 - 字符串对象的内容不能   创建对象后更改,尽管语法可以实现   好像你可以这样做。例如,当您编写此代码时,   编译器实际上创建了一个新的字符串对象来保存新的   字符序列,并将新对象分配给b。该   字符串“h”然后有资格进行垃圾收集。

答案 2 :(得分:5)

C#使用==标记来表示三个不同的运算符:一个可重载的等式检查运算符(如果对于所讨论的确切类型存在重载,则可用于类类型或值类型),不可重载的引用标识-check运算符(要求两个操作数都是类引用,并要求类型不相互排斥),以及一个空检查运算符(可用于任何类类型,可空值类型或泛型,可能是其中之一)以上)。虽然大多数形式的重载是在.NET语言中以统一的方式定义的,但是对于所有这三种相等使用一个运算符则不然。其他语言如VB.NET对第一种形式使用不同的标记(例如,在VB.NET中,表达式(x = y)使用相等测试重载(如果定义了一个),或者如果没有则生成语法错误; {{1测试(x Is y)x是否标识相同的对象实例,而不考虑是否存在重载的相等运算符。

转换为y的目的是确保Object标记被解释为表示reference-identity-check运算符而不是可重载的等于运算符;只有因为C实现==运算符的方式才需要这样的强制转换,而在VB.NET等其他语言中则不需要。

答案 3 :(得分:1)

评论代码

因此,如果值“xx”在运行时设置为相同的“xx”值,那么您将得到不同的false结果,因为编译器没有机会在运行时进行优化,即使它是两种情况下的代码和输入值相同,预编译与运行时的结果不同。

private void button1_Click(object sender, EventArgs e)
{
    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
}

private void button2_Click(object sender, EventArgs e)
{
    string a = textBox1.Text; //type in xx at runtime
    string b = textBox2.Text; //type in xx at runtime
    string c = textBox3.Text; //type in just "x" at runtime
    string d = String.Intern(c + c);

    Console.WriteLine((object)a == (object)b); // False with runtime values that have the same value
    Console.WriteLine((object)a == (object)d); // False 
    Console.WriteLine(a == d); // True - the Equals Operator of the string works as expected still 
}