Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# “铸造”的目的是什么;“对象”;类型?_C#_.net_String_Equality_String Interning - Fatal编程技术网

C# “铸造”的目的是什么;“对象”;类型?

C# “铸造”的目的是什么;“对象”;类型?,c#,.net,string,equality,string-interning,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本身就是字符串的对象,那么再次强制转换为对象类型的目的是什么呢?

我在一个网站上找到了如下代码

 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本身就是字符串的对象,那么再次强制转换为对象类型的目的是什么呢?

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

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

另一件需要提及的事情是在.NET中

那么为什么是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”,因为
a
b
对内存中两个不同字符串的引用,这两个字符串看起来都像“xx”。

是对所提供答案的补充:

System.String类是中提供的不可变引用类型 NET framework类库。此类将创建一个新字符串 对象,用于任何字符串操作操作。内容 这种类型的对象不会改变,尽管语法使其改变 似乎内容可以更改。此外,字符串用作 哈希表键用于计算哈希值,以避免 正在破坏哈希数据结构

示例:

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";

// 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";
这将创建另一个对象:

string b = "h"; 
b += "ello";
下面将创建对现有对象的引用,更准确地说,它将指向变量“a”指向的同一对象→ “你好”

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

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

对象进行强制转换的目的是确保
==
标记被解释为代表一个引用身份检查运算符而不是一个可重载的相等运算符;这种强制转换之所以需要,是因为C如何实现
=
运算符,而在其他语言(如VB.NE)中不需要T.

用代码注释

因此,如果在运行时将值“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 
}

绝对没有。System.String继承自System.object无需强制转换…该代码的作者希望调用
运算符==(对象,对象)
(引用相等),而不是(就重载解析而言,更适合)
运算符==(字符串,字符串)
(值相等),因此cast.Operator调用不是多态的,它们在编译时解析。另一种方法是调用
object.ReferenceEquals()
没有类型转换。对类型系统的颠覆。该网站缺少解释发生了什么的代码;即,如果我们有
字符串e=c+c;
那么
e
a
将不会使用“对象”进行相等比较版本,但只使用==而不使用强制转换来比较equal。这是理解字符串插入的关键点:它在保持值比较不变的同时更改引用比较。手动构造字符串时,插入是否需要显式?(如问题中所示)对字符串进行值检查@Carl@dotctor但是,在这种情况下,正如您所解释的,a的引用等于引用b,更改b的值应该导致更改a的值。字符串是引用类型,并且它引用了堆中的对象。字符串在.NET中是不可变的。因此,您不能更改值oLegendsCompiler在编译时使用字符串内部处理来完成它。
a
也引用相同的s