使void成为原始类型的设计原理是什么?

时间:2017-03-17 09:46:50

标签: c# language-lawyer

Type.IsPrimitive类型上使用反射void时返回false。从C ++背景中进行复制,这是令人惊讶的。

查看C# 6.0 spec(页82)未提及void类型,这可能意味着它未被完全归类为类型。

语言规范中是否有任何内容将void归类为其他内容。还是其他任何讨论或提及其背后原因的讨论?

3 个答案:

答案 0 :(得分:47)

为什么原始类型无效?因为它不是你可以实例化的东西。它不是原始类型,也不是引用类型。它什么都没有。

Eric Lippert在this post on Software Engineering中描述了与void类型有关的一些“问题”,其中详细介绍void作为在委托中使用的类型和Action s:

  

类型系统本质上是一个系统,用于对特定值上的哪些操作有效进行逻辑演绎; void返回方法不返回值,因此问题“什么操作对此事件有效?”根本没有任何意义。没有“事情”可以进行操作,有效或无效。

使其成为原始类型会破坏VES(虚拟执行系统)中void的特殊含义和目的,正如Eric后面解释的那样:

  

调用void方法的效果与调用非void方法的效果根本不同;非void方法总是在堆栈上放置一些东西,可能需要弹出。 void方法永远不会把东西放在堆栈上。

使void原始类型违反了这条规则,尽管你可以证明它的用处,正如Eric在引用的帖子中进一步解释的那样。

答案 1 :(得分:12)

void不是类型,而是关键字。就像它在C ++中一样,意味着完全相同的东西。关键词在语言中扮演崇高的角色,它们只能出现在某些地方,并且允许解析器对程序员的意图做出严格的假设。

主要是生成良好的错误消息。在声明为void的方法中,如return 42;这样的声明显而易见,你会得到一个清晰的"嘿,你说它不会返回任何东西"错误信息。不太明显的是,它们对于从基本语法错误中恢复非常有用,缺少}右括号例如是一个非常难以恢复的错误。当解析器在解析方法体时遇到void,然后它可以重置解析器状态并再次开始生成良好的错误消息。

System.Void 类型完全存在是与元数据相关的怪癖。粗略等效于C ++中的.h文件。它们主要用于处理C ++中的技术限制,它没有模块的概念,它使用单通道编译模型并要求声明始终出现在定义之前。在C ++中非常痛苦的繁忙工作,虽然编辑器工具可以帮助一点。在C#中没有这样的限制,编译器会从定义中生成声明。

元数据详细描述了一种方法,存储在元数据中的MethodDef和MethodDefSig记录中。 CLR设计者可以用两种基本方式表达"这种方法不会返回数据"。一个显而易见的方法是,他们可以使用MethodAttributes enum中的一些内容,例如" HasNoReturnValue"。但是由于许多方法确实具有非void返回类型,并且在MethodDefSig记录中保留了空间,因此他们只选择 sentinel值作为返回类型。 System.Void。

反映System.Void类型通常没用。实际上,他们可以为IsPrimitive选择任何值,但它不会产生任何影响。假是一个合乎逻辑的选择,它没有描述一种类型。

答案 2 :(得分:8)

从阅读C#规范,没有提到类型 void。它被写成return type。在目录中,它未按引用或值类型分类。它被称为关键字。

typeof功能部分说:

  

typeof-expression的第三种形式包括一个typeof关键字,后跟一个带括号的void关键字。此表单的表达式的结果是System.Type对象,表示缺少类型。 typeof(void)返回的类型对象与为任何类型返回的类型对象不同。这个特殊类型对象在允许反射到语言中的方法的类库中很有用,其中这些方法希望有一种方法来表示任何方法的返回类型,包括void方法,以及System.Type的实例。

对我而言,void表示void具有关联类型,但仅用于您希望反射因类型系统而为您提供有形内容的情况。否则for loop只是一个关键字。