转换null不会编译

时间:2012-01-25 18:43:17

标签: 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;

这给了我一个与此类似的编译错误:Can't cast source type object to target type string

为什么呢?不是null只是一堆零指向“无处”的内存地址,无论类型是什么?

7 个答案:

答案 0 :(得分:23)

问题不在于null,而是object无法分配给string。这很好用

string x = (string)null;

如果删除强制转换(string x = null),其工作原理在C#语言规范的第2.4.4.6节中列出

  

null-literal可以隐式转换为引用类型或可空类型

当您引入演员表({{​​1}})时,您不再拥有空文字。相反,您的值为(object)null。它基本上没有什么不同

object

答案 1 :(得分:11)

这里的问题基本上是“为什么编译器没有考虑到它知道指定的值是一个已知为null的常量引用这一事实?”

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

在我看来,代码很可能是一个错误;当然编译器应该告诉你它而不是允许它。

答案 2 :(得分:5)

  

不是null只是一堆零指向“无处”的内存地址,无论类型是什么?

这就是C或C ++等弱类型语言。

在C#中,引用的类型是其标识的组成部分。 (string)null(object)null不同,因为其中一个是string,一个是object

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

答案 3 :(得分:3)

它需要是可分配的 - 即使它看起来像是“相同的null”并且无关紧要,编译器仍然支持该类型。这样做的一个优点是解决了重载问题:

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

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

答案 4 :(得分:2)

也许object x = (string) null;可能有用,但为什么会这样?

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

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

答案 5 :(得分:0)

您可以为任何引用类型的变量赋值null,而不会抛出任何内容:

String x = null;

答案 6 :(得分:0)

每个班级都有以下定义列表:

Constructors
Destructors
Fields
Methods
Properties
Indexers
Delegates
Events
Nested Classes

Object是一种泛型类型,因为每个类都是从它继承而不是从其他方式继承。这些定义对于每个类都不相同,因此您的编译器可以决定您可以为彼此分配/强制转换的类型。

然后你做:string x = (object)null;

编译器并不关心你试图首先分配给x的值,但它会检查字符串的类型定义,并且不要让你自己开枪,并产生错误,因为它是类型不匹配。