强制转换 null 不会编译

本文关键字:编译 null 转换 | 更新日期: 2023-09-27 18:21:29

>无意中,我写了以下代码行:

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不就是一堆指向"无处"内存地址的零,无论类型是什么吗?

强制转换 null 不会编译

问题不在于null的铸造,而在于object不能分配给string。 这工作正常

string x = (string)null;

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

null

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

当你引入一个强制转换((object)null(的那一刻,你不再有一个空文本。 相反,您有一个类型 object 的值。 它本质上与

object temp = null;
string x = temp;

这里的问题基本上是"为什么编译器不考虑它知道分配的值是已知为 null 的常量引用这一事实?

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

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

null 不就是一堆指向"无处"内存地址的零,无论类型是什么吗?

这就是像 C 或 C++ 这样的弱类型语言的全部内容。

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

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

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

void Foo(object bar) { ... }
void Foo(string bar) { ... }
Foo((object)null); // will call the former
Foo((string)null); // will call the latter

也许object x = (string) null;这可能有效,但你为什么要这样做呢?

因为对象可以容纳字符串

,但字符串不能容纳对象

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

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

String x = null;

每个类都有一个定义列表:

Constructors
Destructors
Fields
Methods
Properties
Indexers
Delegates
Events
Nested Classes

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

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

编译器并不关心你首先尝试分配给x的值,但它会检查字符串的类型定义,只是不让你射击自己的腿,并生成错误,因为它是类型不匹配。