【问题标题】:How do I tell the Roslyn C# compiler to use a specific version of .NET?如何告诉 Roslyn C# 编译器使用特定版本的 .NET?
【发布时间】:2019-09-24 14:40:44
【问题描述】:

我发现 Roslyn 附带的 csc.exe 二进制文件可以使用 -langversion:<string> 命令行参数来设置我要编译的 C# 版本。但是如何选择我希望编译器使用的 .NET 版本?

对于我使用一些 .NET SQL Server 功能的简单测试程序,编译过程工作得很好,所以我知道编译器在我的计算机上以某种方式使用了 .NET 版本。我的C:\Windows\Microsoft.NET\Framework 目录中有多个.NET 版本,我假设编译器正在使用其中之一。我想在编译我的程序时明确设置编译器使用的 .NET 版本。

注意:如果您能详细说明一下编译器如何首先选择一个版本,那也将不胜感激。

【问题讨论】:

  • 安装的每个 .net 版本都应该有自己的csc.exe
  • 我知道这一点。但是,我没有使用任何与 .NET 版本捆绑在一起的 csc.exe 二进制文件。 Roslyn 可以通过nuget.exe 自行下载,并可以在任何地方运行。
  • 没有这样的东西。目标框架版本是一个 MSBuild 项目属性,这会导致在编译期间使用不同的引用程序集集。
  • 如果这是真的,那么我的 Roslyn 目录中的 csc.exe 二进制文件如何能够在不通过 msbuild 调用的情况下构建我的程序?它必须以某种方式自动找到要使用的 .NET 框架版本,因为我将 Roslyn 与 .NET 分开安装,并且我的系统上有多个可用的 .NET 版本。那么从逻辑上讲,我不应该能够直接控制这种行为吗?

标签: .net roslyn csc


【解决方案1】:

简短的回答是,您的关系搞错了:csc.exe 取决于 Roslyn,反之亦然。

长答案需要简短的历史课:

最初在 .NET 框架中,csc.exe 是一个独立的二进制文件,负责将 C# 源代码编译为 IL。但它是不透明的,而且它的命令行界面限制了调用它所能达到的效果。

Microsoft 引入了 System.CodeDom 命名空间和类作为他们自己的工具生成代码的一种方式(例如 Visual Studio 中的 Windows 窗体设计器),但几乎每个人都开始使用它,因为它比 csc.exe 好几英里。然而,考虑到它的创建目的,CodeDOM 受到许多限制和边缘情况的困扰,这使得它对于某些非编译任务来说并不理想 - 最终它只是调用 csc.exe 来生成编译代码。

最终,这种方法无法满足 Microsoft 自己在其旗舰 IDE 中对其代码进行更好的静态分析的需求。为了实现这一要求,需要一个新的 API,微软意识到,如果他们将其设计为普通开发人员可以访问,他们可以用一块石头杀死两只鸟。于是,Roslyn 项目诞生了:一套完整的独立完整的 API,任何人都可以使用,从而满足开发人员和 Visual Studio 的需求。

最终的结果是所有原本存在于csc.exe 中的逻辑都迁移到了Roslyn 的API 中,而the way those APIs are invoked 决定了将使用哪个C# 语言版本。将-langversion 传递给csc.exe/p:TargetFrameworkVersion 传递给msbuild.exe 最终会设置Roslyn 语言版本进行编译,但没有什么能阻止您创建自己的Roslyn 编译实例来实现相同的目的。

参考:https://stackoverflow.com/a/7854697/70345

【讨论】:

  • 所以基本上你是说当我通过 -langversion 参数指定 C# 版本时,Roslyn 在幕后做了一些事情来匹配 C# 版本与 .NET 框架的版本,并且当 @ 987654334@ 与 /p:TargetFrameworkVersion 一起使用,然后 Roslyn 在实际编译之前将提供的 .NET 框架版本与 C# 语言版本匹配?如果是这样,那么创建 Roslyn 编译实例似乎是手动配对两个特定版本的 C# 和 .NET 的唯一方法。
【解决方案2】:

我只是从命令行使用这个(即2.0以下)

msbuild <project-or-solution> /p:TargetFrameworkVersion=v2.0

【讨论】:

  • Roslyn 没有包含msbuild,据我了解,msbuild 无论如何都只是在下面使用csc.exe。由于 Roslyn 包含的 csc.exe 二进制文件显然能够使用自己的 .NET 版本进行编译,因此必须有一种方法可以直接告诉 csc.exe 我要使用哪个 .NET 版本。
【解决方案3】:

假设 csc 是一个相当新的版本,

csc -langversion:?

会告诉你csc的构建默认使用哪个版本的语言1

来自对另一个答案的评论:

必须有办法直接告诉 csc.exe 我要使用哪个 .NET 版本

有,并且您已经在问题的第一行中确定了它 - 传递一个 -langversion 参数。


如果您想知道应该使用哪个版本,请使用默认版本。如果它没有抱怨 syntax 错误,那么它可能已经足够好了。如果您使用特定的语言功能,您可以尝试"What's new in C# x.x" 文档来确定它是在哪个版本中引入的。


1如果它给你一个错误,它不支持它。改为运行csc /?-langversion 的文档应列出支持的版本。默认是最后列出的版本号。

【讨论】:

  • 我的印象是,实际的 C# 语言和 .NET 框架在某种程度上被认为是独立的,允许您随意混合和匹配版本只要您愿意不要使用至少依赖于特定版本的 .NET 框架的任何 C# 语言功能。您是说-langversion 参数自动暗示某些.NET 版本以及显式提供的C# 语言版本?因为如果是这样,那么这似乎表明 C# 版本与 .NET 版本紧密耦合,这似乎不正确。
  • @Damien_The_Unbeliever 我相信语言版本(例如 C# 7 与 C# 4)大部分独立于 .NET 版本(例如 .NET 4.5 与 .NET 3.5)。如果我理解正确,可能无法从csc 指定.NET 版本。您最终必须手动链接正确的系统 DLL。 (或使用 msbuild)
  • 但这再次引起了人们对 Roslyn csc.exe 二进制文件如何设法以某种方式首先使用 .NET 自行编译的同样困惑。它必须以某种方式自己知道在哪里可以找到正确的 DLL。这是在哪里配置的,我如何控制它?我确实发现包含的csc.rsp 文件有一个通用框架DLL 文件名列表,除非指定-noconfig,否则应该自动包含这些文件名,但是它如何选择查找这些文件名的路径?我想如果我可以控制这条路径,那么我可以控制我包含哪个 .NET 版本。
猜你喜欢
  • 1970-01-01
  • 2012-06-25
  • 1970-01-01
  • 2010-10-18
  • 2015-06-11
  • 2017-06-13
  • 1970-01-01
  • 2021-09-27
相关资源
最近更新 更多