.NET 目标框架兼容性和编译器 - 在 .NET 4.5 或更高版本上

7

我在.NET开发方面有相当的经验,但今天我被迫思考一个我以前从未想过的问题:

安装的.NET Framework、Visual Studio中的.NET Framework目标和C#编译器如何协同工作?

具体例子: System.dll 包含枚举 System.Net.SecurityProtocolType。在.NET 4.5上,该枚举包含成员 SSl3TlsTls11Tls12。在.NET 4.7上,添加了成员 SystemDefault

因此,针对.NET 4.7.x,这段代码可以编译:

var p = SecurityProtocolType.SystemDefault;

然而,当我针对.NET 4.5.x时,这段代码无法编译(正如我们所预期的那样)。令我困惑的是,既然.NET 4.7是.NET 4.5的“原地升级”,即在安装.NET 4.7时,将.NET 4.5的System.dll替换为.NET 4.7的dll,为什么这会起作用呢?编译器是通过某种API文件来知道我不能在.NET 4.5上使用SystemDefault,但可以在4.7上使用吗?
附带事实:当我针对.NET 4.5并安装了.NET 4.7时,调用Enum.GetValues(typeof(SecurityProtocolType)将给我SecurityProtocolType.SystemDefault。所以,我非常确定我的.NET 4.5应用程序使用的是.NET 4.7 System.dll。

1
您的计算机有不同的参考程序集,C#编译器使用与您选择的目标匹配的程序集。可以在c:\program files (x86)\reference assemblies目录中找到它们。这样做是为了让您构建一个可以在另一台计算机上运行的程序,该计算机使用较旧版本的.NET或完全不同的框架版本,如Silverlight、UWP和.NETCore目标。 - Hans Passant
2个回答

7
编译器如何知道我在.NET 4.5上不能使用SystemDefault,但可以在4.7上使用?这是通过某种API文件告诉编译器的吗?
是的,我希望它是通过参考程序集来完成的。引用程序集是一个仅包含可访问的API定义的程序集。
在我的Windows机器上,这些位于C:\ Program Files(x86)\ Reference Assemblies \ Microsoft \ Framework \ .NETFramework中。

4
当你指定 .NET Framework 4.5 的目标时,你正在指定该 API 的接口表面。编译器使用这个确切的版本来确定哪些类型是可用的。
当在目标机器上存在 .NET Framework 4.7 运行时,类型将从 4.5 转发到 4.7,但这只是运行时的行为。它并不改变应用程序编译时的 .NET Framework 4.5 的目标事实。请记住,当程序集部署到目标计算机上时,它已经被编译成中间语言。在运行时编译器根本没有参与,因此不能动态地更改目标框架。
至于你提到的旁注,那就是 Reflection 的运行时行为,它的工作方式是因为它使用的运行时框架是 4.7。

请问一下,当构建目标为 .net 4.5 且 .net 4.7 存在时,能否再解释一下运行时会使用 .net 4.7 的情况?也就是说,最高版本的 .net framework 将在运行时被使用?如果我有误,请纠正我,谢谢。 - programtreasures
基本上,当任何版本的.NET Framework Runtime 4.0+安装在计算机上时,它将替换先前的版本并重新定位为使用已安装的最新版本。这与大多数其他.NET Framework Runtime安装的行为不同,后者可以并行运行。 - NightOwl888

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接