Как указать компилятору Roslyn C# использовать определенную версию .NET?

Я обнаружил, что двоичный файл csc.exe, поставляемый с Roslyn, может принимать аргумент командной строки -langversion:<string>, чтобы установить версию C#, которую я хотел бы скомпилировать. Но как мне выбрать, какую версию .NET использовать компилятор?

Процесс компиляции отлично работает для моей простой тестовой программы, использующей некоторые функции .NET SQL Server, поэтому я знаю, что компилятор каким-то образом использует версию .NET на моем компьютере. В моем каталоге C:\Windows\Microsoft.NET\Framework есть несколько версий .NET, и я предполагаю, что компилятор использует одну из них. Я хотел бы явно указать, какую версию .NET использует компилятор при компиляции моей программы.

Примечание. Если вы можете немного подробнее рассказать о том, как компилятор в первую очередь выбирает версию, мы также будем весьма признательны.


person Aaron Beaudoin    schedule 24.09.2019    source источник
comment
Каждая установленная версия .net должна иметь свой собственный csc.exe.   -  person Bradley Uffner    schedule 24.09.2019
comment
Я знаю об этом. Однако я не использую какой-либо двоичный файл csc.exe, связанный с версией .NET. Roslyn можно скачать отдельно с помощью nuget.exe и запускать из любого места.   -  person Aaron Beaudoin    schedule 24.09.2019
comment
Такого нет. Версия целевой платформы — это свойство проекта MSBuild, что приводит к тому, что во время компиляции используются разные наборы сборок, на которые ссылаются.   -  person Lex Li    schedule 24.09.2019
comment
Если это правда, то как двоичный файл csc.exe в моем каталоге Roslyn может построить мою программу без вызова через msbuild? Он должен каким-то образом автоматически находить версию .NET framework для использования, поскольку я установил Roslyn отдельно от .NET и потому что в моей системе доступно несколько версий .NET. По логике вещей, разве я не могу напрямую контролировать это поведение?   -  person Aaron Beaudoin    schedule 24.09.2019


Ответы (3)


Короткий ответ заключается в том, что у вас неправильное отношение: csc.exe зависит от Рослин, а не наоборот.

Длинный ответ требует краткого урока истории:

Первоначально в среде .NET csc.exe был автономным двоичным файлом, отвечающим за компиляцию исходного кода C# в IL. Но он был непрозрачным, а его интерфейс командной строки ограничивал то, чего можно было добиться, вызывая его.

Microsoft представила пространство имен и классы System.CodeDom как способ для собственных инструментов генерировать код (например, конструктор Windows Forms в Visual Studio), но почти все начали его использовать, потому что оно было намного лучше, чем csc.exe. Однако, учитывая то, для чего он был создан, CodeDOM страдает от многочисленных ограничений и пограничных случаев, которые делают его менее чем идеальным для определенных задач, не связанных с компиляцией, и в конце концов он просто вызывает csc.exe для создания скомпилированного кода.

В конечном итоге этот подход не смог удовлетворить собственные потребности Microsoft в улучшении статического анализа кода в их флагманской IDE. Для выполнения этого требования требовался новый API, и в Microsoft поняли, что если они сделают его доступным для обычных разработчиков, то смогут убить двух зайцев одним выстрелом. Так родился проект Roslyn: полный набор независимых и полных API-интерфейсов, которые может использовать любой, тем самым удовлетворяя потребности как разработчиков, так и Visual Studio.

Конечным результатом является то, что вся логика, существовавшая в версии csc.exe, была перенесена в API-интерфейсы Roslyn и способ вызова этих API определяет, какая версия языка C# будет использоваться. Передача -langversion в csc.exe или /p:TargetFrameworkVersion в msbuild.exe в конечном итоге приводит к установке языковой версии Roslyn для компиляции, но ничто не мешает вам создать собственный экземпляр компиляции Roslyn для достижения того же самого.

Ссылка: https://stackoverflow.com/a/7854697/70345

person Ian Kemp    schedule 24.09.2019
comment
По сути, вы говорите, что когда я указываю версию C# через параметр -langversion, Roslyn делает что-то за кулисами, чтобы сопоставить эту версию C# с версией .NET framework, и что когда msbuild используется с /p:TargetFrameworkVersion, тогда Roslyn соответствует предоставленному . NET framework с версией языка C# до фактической компиляции? Если это так, то кажется, что создание экземпляра компиляции Roslyn будет единственным способом вручную соединить две определенные версии C# и .NET. - person Aaron Beaudoin; 24.09.2019

Я просто использую это из командной строки (т.е. 2.0 ниже)

msbuild <project-or-solution> /p:TargetFrameworkVersion=v2.0
person leppie    schedule 24.09.2019
comment
Roslyn не включает msbuild, и, насколько я понимаю, msbuild в любом случае просто использует csc.exe внизу. Поскольку двоичный файл csc.exe, входящий в состав Roslyn, явно может компилироваться с использованием версии .NET сам по себе, должен быть способ напрямую сообщить csc.exe, какую версию .NET я хочу использовать. - person Aaron Beaudoin; 24.09.2019

Предполагая относительно недавнюю сборку csc,

csc -langversion:?

Сообщит вам, какая версия языка используется в сборке csc по умолчанию1.

Из комментария к другому ответу:

должен быть способ напрямую сообщить csc.exe, какую версию .NET я хочу использовать

Есть, и вы уже определили его в первой строке вашего вопроса — передайте параметр -langversion.


Если вы хотите знать, какую версию вам следует использовать, просто используйте версию по умолчанию. Если он не жалуется на синтаксические ошибки, скорее всего, он достаточно хорош. Если вы используете определенные функции языка, вы можете попробовать "Что нового в C# xx", чтобы выяснить, в какой версии он был представлен.


1Если он выдает ошибку, он его не поддерживает. Вместо этого запустите csc /?, и в документации для -langversion должны быть перечислены поддерживаемые версии. По умолчанию используется последний указанный номер версии.

person Damien_The_Unbeliever    schedule 24.09.2019
comment
У меня сложилось впечатление, что фактический язык C# и платформа .NET считаются в некоторой степени независимыми, что позволяет вам смешивать и сопоставлять версии, как вы хотите, до тех пор, пока вы не используете какие-либо функции языка C#, которые зависят по крайней мере на определенной версии .NET framework. Вы говорите, что аргумент -langversion автоматически подразумевает некоторую версию .NET вместе с явно предоставленной версией языка C#? Потому что если это так, то это указывает на то, что версии C# тесно связаны с версиями .NET, что кажется неправильным. - person Aaron Beaudoin; 24.09.2019
comment
@Damien_The_Unbeliever Я считаю, что языковая версия (например, C# 7 против C# 4) в основном не зависит от версии .NET (например, .NET 4.5 против .NET 3.5). Если я правильно понимаю, вероятно, нет способа указать версию .NET из csc. Вам придется в конечном итоге связать правильные системные библиотеки DLL вручную. (или с помощью msbuild) - person JoshVarty; 24.09.2019
comment
Но это снова вызывает ту же путаницу, что и двоичный файл Roslyn csc.exe каким-то образом умудряется компилироваться сам по себе с .NET. Он должен каким-то образом сам знать, где найти правильные библиотеки DLL. Где это настраивается и как это контролировать? Я обнаружил, что включенный файл csc.rsp имеет список общих имен файлов DLL фреймворка, которые должны автоматически включаться, если не указано -noconfig, но как он выбирает, какие пути искать для этих имен файлов? Я полагаю, что если я могу контролировать этот путь, то я могу контролировать, какую версию .NET я включаю. - person Aaron Beaudoin; 25.09.2019