C# 强制转换空不';不编译

C# 强制转换空不';不编译,c#,.net,compiler-construction,null,C#,.net,Compiler Construction,Null,在工作中,我意外地编写了以下代码行: string x = (object) null; // It was var x = (object)null and I changed from var to string instead of // object x = null; 这给了我一个类似的编译错误:无法将源类型对象强制转换为目标类型字符串 为什么??null不就是一堆指向“nowhere”内存地址的零吗,不管类型是什么 问题不在于null的强制转换,而是对象不能分配给字符串。这个很

在工作中,我意外地编写了以下代码行:

string x = (object) null; 
// It was var x = (object)null and I changed from var to string instead of 
// object x = null;
这给了我一个类似的编译错误:
无法将源类型对象强制转换为目标类型字符串


为什么??
null
不就是一堆指向“nowhere”内存地址的零吗,不管类型是什么

问题不在于
null
的强制转换,而是
对象
不能分配给
字符串
。这个很好用

string x = (string)null;
如果删除强制转换(
string x=null
),则此操作有效的原因在C语言规范的第2.4.4.6节中给出

空文本可以隐式转换为引用类型或可空类型

当您引入强制转换(
(object)null
)时,您就不再具有null文本。相反,您有一个类型为
object
的值。基本上,这和

object temp = null;
string x = temp;
可能
objectx=(string)null这可能行得通,但你为什么要这么做

因为对象可以容纳字符串,但字符串不能容纳对象


字符串是从对象继承的,而不是从相反的方向继承的。

您可以为引用类型的任何变量赋值null,而无需强制转换任何内容:

String x = null;

它需要是可赋值的——即使它看起来是“相同的null”,而且不重要,编译器仍然支持该类型。这样做的一个优点是可以解决重载问题:

void Foo(object bar) { ... }
void Foo(string bar) { ... }

Foo((object)null); // will call the former
Foo((string)null); // will call the latter

这里的问题基本上是“为什么编译器不考虑这样一个事实,即它知道赋值是一个已知为null的常量引用?”

答案是:为什么要这样做?考虑到这些信息有什么令人信服的好处?您故意说“我希望将此表达式视为object类型”,并且不能将object类型的值赋给string类型的变量。在这种情况下允许这样做有什么好处

在我看来,代码很可能是一个bug;当然,编译器应该告诉您这一点,而不是允许您这样做

不管是什么类型的内存地址,null不是仅仅是一堆指向“无处”内存地址的零吗

<>这是一个弱类型的语言,如C或C++。 在C#中,引用的类型是其标识的一个组成部分
(string)null
(object)null
不同,因为一个是
字符串
,一个是
对象


此外,在C#
中,null
实际上没有数字等价物。C#中的引用与指针不同,从语义上讲,它们没有关联的内存地址
null
仅表示引用不指向对象,而
null
引用的内部表示是一个实现细节。

每个类都有一个定义列表,用于:

Constructors
Destructors
Fields
Methods
Properties
Indexers
Delegates
Events
Nested Classes
对象是泛型类型,因为每个类都是从它继承的,但不是从它继承的。这些定义对于每个类都不相同,因此编译器可以决定可以相互分配/转换哪些类型

然后执行:
stringx=(object)null


编译器并不关心您首先要分配给x的值,但它会检查字符串的类型定义,只是不允许您自己动手,并生成一个错误,因为这是一个类型不匹配的问题。

为什么不分配
string x=string.empty?为什么要强制转换
stringx=null
。你刚才说过
stringx=null你不会有这个问题。但你不是这么说的。你说的是
string x=someObj
其中someObj是恰好为空的
对象。就编译器而言,您有一个试图分配给字符串的对象引用,这是不合法的。@harold。你是对的,这是错误的,但我仍然很有兴趣知道。你需要显式强制转换来向下转换
对象
字符串
的引用。因此使用
stringx=(string)(object)null。对吧?;-)我知道我该怎么修。我在问空对象和空字符串之间有什么区别?你仍然认为它是“空”的,但你说它是一种特殊类型的对象。@gdoron空对象和空字符串之间有什么区别?他们的类型,这使世界上所有的不同。类似于问
(float)3
(int)3
有什么不同。@gdoron我更新了我的答案,进一步解释了语义here@Lagrangian这是C#3.5语言规范的第2.4.4.6节。它可以从这个页面上的链接下载一个有趣的答案!但让我们假设(object)null隐式转换为string。重载解析算法仍然会选择对象版本,因为这是一个精确的类型匹配。重载解析算法总是说,在决定两种方法中哪一种更好时,身份转换比任何其他转换都好。我应该更多地访问你的博客(并重读Jon Skeet)。在使用C#8年之后,我仍然必须在VS中检查上面的代码,看看它是否真的有效谢谢,明白了。但是空
对象
和空
字符串
引用相同的内存地址是真的吗?@gdoron:memory address?你称之为“内存地址”的东西是什么?空引用是一个引用。实际上,当然,引用通常是作为地址实现的。但它不必如此;例如,引用可以被处理到由垃圾收集器维护的大表中。不要把参考资料当作地址;可以把它们看作是引用某物的抽象概念。@gdoron:现在我们已经解决了这个问题:空对象和空字符串引用的是同一事物吗?不,当然不是。他们没有提到任何东西。这样想吧。我有一张写着“最爱的冰”的纸