IEnumerable<T>、Task<T> 和 IDisposable 是否在 C# 编译器中进行了硬编码?
Are IEnumerable<T>, Task<T> and IDisposable hard coded in the C# compiler?
这个问题我自己问过很多次。我试图找到一些关于此的博客 post,甚至深入研究了 Roslyn 源代码,但还没有找到任何完整的答案。
基本上,借助一些现代 C# 语言功能,编译器会采用一些语法糖并将其转换为更低级的 C# 代码。其中的一些例子是:
using()
生成一个 try-finally
来明确处理一个 IDisposable
- 函数 return 将
IEnumerable<T>
与 yield return
结合起来会将那个函数变成一个作为状态机实现的迭代器
- 标有
async
的函数必须returnTask<T>
(或类似)并且也会变成状态机,可以从程序事件循环中重新进入引擎盖下
因此,这些都是不错的功能,但编译器始终强制执行特定类型 IEnumerable<T>
、Task<T>
和 IDisposable
。 这些类型是否以某种方式融入了编译器?编译器是否以某种方式绑定到标准库,即使 mscorlib
只是提供通用功能的普通 C# 代码?
我无法想象,因为编程语言是如此抽象和通用。正如我所看到的,只要类型具有 GetAwaiter
扩展方法,就可以 await
-ing 任何东西。这对我来说听起来更抽象。
编辑
此外,如果有人可以指出在编译器中指定所需预定义类型的源代码,请告诉我!
排序。
编译器有 "special"(在类型系统/绑定器中使用)和 "well-known"(由生成的代码引用)类型和成员的列表,它们在 Roslyn 中按名称硬编码资源。但是,它只关心这些类型/成员的名称和方法/签名;你仍然可以编写自己的 mscorlib(人们已经这样做了),只要它有它们。
见
这个问题我自己问过很多次。我试图找到一些关于此的博客 post,甚至深入研究了 Roslyn 源代码,但还没有找到任何完整的答案。
基本上,借助一些现代 C# 语言功能,编译器会采用一些语法糖并将其转换为更低级的 C# 代码。其中的一些例子是:
using()
生成一个try-finally
来明确处理一个IDisposable
- 函数 return 将
IEnumerable<T>
与yield return
结合起来会将那个函数变成一个作为状态机实现的迭代器 - 标有
async
的函数必须returnTask<T>
(或类似)并且也会变成状态机,可以从程序事件循环中重新进入引擎盖下
因此,这些都是不错的功能,但编译器始终强制执行特定类型 IEnumerable<T>
、Task<T>
和 IDisposable
。 这些类型是否以某种方式融入了编译器?编译器是否以某种方式绑定到标准库,即使 mscorlib
只是提供通用功能的普通 C# 代码?
我无法想象,因为编程语言是如此抽象和通用。正如我所看到的,只要类型具有 GetAwaiter
扩展方法,就可以 await
-ing 任何东西。这对我来说听起来更抽象。
编辑
此外,如果有人可以指出在编译器中指定所需预定义类型的源代码,请告诉我!
排序。
编译器有 "special"(在类型系统/绑定器中使用)和 "well-known"(由生成的代码引用)类型和成员的列表,它们在 Roslyn 中按名称硬编码资源。但是,它只关心这些类型/成员的名称和方法/签名;你仍然可以编写自己的 mscorlib(人们已经这样做了),只要它有它们。
见