Поддерживает ли C # 8 .NET Framework?

134

В настройках расширенной сборки Visual Studio 2019 C # 8 недоступен для проекта .NET Framework, только (как показано на рисунке ниже) для проекта .NET Core 3.0:

введите описание изображения здесь

Поддерживает ли C # 8 .NET Framework?

Джеймс Харкорт
источник

Ответы:

244

Да, C # 8 можно использовать с .NET Framework и другими целями старше .NET Core 3.0 / .NET Standard 2.1 в Visual Studio 2019 (или более старых версиях Visual Studio, если вы устанавливаете пакет Nuget ).

Языковая версия должна быть установлена 8.0в файле csproj.

Большинство - но не все - функции доступны в зависимости от целевой платформы.


Функции, которые работают

Следующие функции предназначены только для изменения синтаксиса; они работают вне зависимости от фреймворка:

Функции, которые можно заставить работать

Для этого требуются новые типы, которых нет в .NET Framework. Их можно использовать только вместе с пакетами Nuget "polyfill" или файлами кода:

Члены интерфейса по умолчанию - не работают

Члены интерфейса по умолчанию не компилируются под .NET Framework и никогда не будут работать, потому что они требуют изменений среды выполнения в среде CLR. .NET CLR теперь заморожен, поскольку .NET Core теперь является шагом вперед.

Для получения дополнительной информации о том, что работает, а что нет, и о возможных полифилах, см. Статью Стюарта Ланга C # 8.0 и .NET Standard 2.0 - Doing Unsupported Things .


Код

Следующий проект C #, ориентированный на .NET Framework 4.8 и использующий ссылочные типы C # 8, допускающие значение NULL, компилируется в Visual Studio 16.2.0. Я создал его, выбрав шаблон библиотеки стандартных классов .NET, а затем отредактировав его для целевой платформы .NET Framework:

.csproj:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFrameworks>net48</TargetFrameworks>
    <LangVersion>8.0</LangVersion>
    <Nullable>enable</Nullable>
  </PropertyGroup>
</Project>

.cs:

namespace ClassLibrary1
{
    public class Class1
    {
        public string? NullableString { get; set; }
    }
}

Затем я попробовал проект WinForms .NET Framework 4.5.2, используя устаревший .csprojформат, и добавил то же свойство ссылочного типа, допускающее значение NULL. Я изменил тип языка в диалоговом окне настроек Visual Studio Advanced Build (отключен в 16.3) на latestи сохранил проект. Конечно, в этой точке он не строится. Я открыл файл проекта в текстовом редакторе и в конфигурации сборки изменил latestего previewна PropertyGroup:

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
   <LangVersion>preview</LangVersion>

Затем я включил поддержку ссылочных типов, допускающих значение NULL, добавив <Nullable>enable</Nullable>к основному PropertyGroup:

<PropertyGroup>
   <Nullable>enable</Nullable>

Я перезагружаю проект, и он строится.


Кровавые подробности

Когда этот ответ был впервые написан, C # 8 находился на стадии предварительной версии, и потребовалось много детективной работы. Я оставляю эту информацию здесь для потомков. Не стесняйтесь пропустить это, если вам не нужно знать все кровавые подробности.

Язык C # исторически был в основном нейтральным к фреймворку, т. Е. Способным компилировать старые версии Framework, хотя для некоторых функций требовались новые типы или поддержка среды CLR.

Большинство энтузиастов C # прочитают запись в блоге Mads Torgersen Building C # 8.0 , в которой объясняется, что некоторые функции C # 8 зависят от платформы:

Все асинхронные потоки, индексаторы и диапазоны полагаются на новые типы фреймворков, которые будут частью .NET Standard 2.1 ... .NET Core 3.0, а также Xamarin, Unity и Mono будут реализовывать .NET Standard 2.1, но .NET Framework 4.8 будет не. Это означает, что типы, необходимые для использования этих функций, не будут доступны в .NET Framework 4.8.

Это немного похоже на кортежи значений, которые были введены в C # 7. Эта функция требовала новых типов - ValueTupleструктур, которые не были доступны в версиях NET Framework ниже 4.7 или .NET Standard старше 2.0. Однако C # 7 все еще можно было использовать в более старых версиях .NET либо без кортежей значений, либо с ними, установив пакет Nuget System.ValueTuple . Visual Studio это понимала, и с миром все было в порядке.

Однако Мадс также писал:

По этой причине использование C # 8.0 поддерживается только на платформах, реализующих .NET Standard 2.1.

... что, если бы оно истинно, исключило бы использование C # 8 с любой версией .NET Framework и даже в библиотеках .NET Standard 2.0, которые только недавно нам было рекомендовано использовать в качестве базовой цели для библиотечного кода. Вы даже не сможете использовать его с версиями .NET Core старше 3.0, поскольку они тоже поддерживают только .NET Standard 2.0.

Началось расследование! -

  • У Джона Скита есть готовая к работе альфа-версия Noda-Time с использованием C # 8, предназначенная только для .NET Standard 2.0. Он явно ожидает, что C # 8 / .NET Standard 2.0 будет поддерживать все платформы семейства .NET. (См. Также сообщение в блоге Джона «Первые шаги со ссылочными типами, допускающими значение NULL» ).

  • Сотрудники Microsoft обсуждали пользовательский интерфейс Visual Studio для ссылочных типов C # 8, допускающих значение NULL, на GitHub , и заявлено, что они намерены поддерживать устаревший csprojформат (формат SDK до .NET Core csproj). Это очень убедительный признак того, что C # 8 можно будет использовать с .NET Framework. [Я подозреваю, что они откажутся от этого теперь, когда раскрывающийся список языковых версий Visual Studio 2019 отключен, а .NET привязан к C # 7.3]

  • Вскоре после известного сообщения в блоге в ветке GitHub обсуждалась кроссплатформенная поддержка. Важным моментом стало то, что .NET Standard 2.1 будет включать маркер, который означает, что поддерживаются реализации интерфейсов по умолчанию - для этой функции требуется изменение среды CLR, которое никогда не будет доступно для .NET Framework. Вот важный момент от Иммо Ландверта, менеджера программы в группе .NET в Microsoft:

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

  • Все это указывает на то, что «C # 8.0 поддерживается только на платформах, реализующих .NET Standard 2.1», что является чрезмерным упрощением, и что C # 8 будет поддерживать .NET Framework, но, поскольку существует такая большая неопределенность, я спросил на GitHub, и HaloFour ответил:

    IIRC, единственная функция, которая определенно не появится в .NET Framework, - это DIM (методы интерфейса по умолчанию), поскольку это требует изменений во время выполнения. Другие функции определяются формой классов, которые, возможно, никогда не будут добавлены в .NET Framework, но могут быть полифилированы с помощью вашего собственного кода или NuGet (диапазоны, индексы, асинхронные итераторы, асинхронное удаление).

  • Виктор Деркс прокомментировал: « Новые атрибуты, допускающие значение NULL, необходимые для разработки более сложных вариантов использования, допускающих значение NULL, доступны только в System.Runtime.dll, который поставляется с .NET Core 3.0 и .NET Standard 2.1 ... [и] несовместим с .NET Framework 4.8 "

  • Тем не менее, Immo Landwerth прокомментировал, что «подавляющему большинству наших API не требуются какие-либо настраиваемые атрибуты, так как типы являются либо полностью универсальными, либо не имеют значения NULL» в статье « Попробовать ссылочные типы, допускающие значение NULL».

  • Бен Холл поднял вопрос о доступности атрибутов, допускающих значение NULL, вне Core 3.0 на GitHub, при этом следует отметить следующие комментарии сотрудников Microsoft:

C # 8 будет полностью поддерживаться только в .net core 3.0 и .net standard 2.1. Если вы вручную отредактируете файл проекта для использования C # 8 с .net core 2.1, вы окажетесь на неподдерживаемой территории. Некоторые функции C # 8 будут работать хорошо, некоторые функции C # 8 будут работать не слишком хорошо (например, низкая производительность), некоторые функции C # 8 будут работать с дополнительными хитростями, а некоторые функции C # 8 не будут работать вообще. Очень сложно объяснить. Мы не блокируем его активно, поэтому это могут сделать опытные пользователи, которые могут перемещаться по нему. Я бы не рекомендовал широко использовать это неподдерживаемое сочетание и совпадение.

(Ян Котас)

Такие люди, как вы, которые хотят понять - и обойти их - могут свободно использовать C # 8. Дело в том, что не все языковые функции будут работать с целями нижнего уровня.

(Иммо Ландверт)


Visual Studio 2019

В RTM-версии Visual Studio 2019 версии 16.3 произошло серьезное изменение - в стартовой версии для C # 8.0: раскрывающийся список выбора языка отключен:

введите описание изображения здесь

Обоснование этого Microsoft :

В дальнейшем ... каждая версия каждой платформы будет иметь одну поддерживаемую версию по умолчанию, и мы не будем поддерживать произвольные версии. Чтобы отразить это изменение в поддержке, эта фиксация навсегда отключает поле со списком языковой версии и добавляет ссылку на документ, объясняющий изменение.

Откроется документ с версией на языке C # . Здесь C # 8.0 указан как язык по умолчанию ТОЛЬКО для .NET Core 3.x. Это также подтверждает, что каждая версия каждой платформы в будущем будет иметь единственную поддерживаемую версию по умолчанию и что на агностицизм языка больше нельзя полагаться.

Языковая версия все еще может быть установлена ​​на 8 для проектов .NET Framework, отредактировав файл .csproj.


Пусть покупатель будет бдителен

Комбинация C # 8 / .NET Framework официально не поддерживается Microsoft. Они говорят, что это только для экспертов.

Стивен Кеннеди
источник
3
Это должно устранить любую путаницу, связанную с тем фактом, что мы можем, если попытаемся, использовать некоторые функции C # 8 за пределами Standard 2.1 - github.com/dotnet/corefx/issues/40039
Бен Холл
2
Новые атрибуты, допускающие значение NULL ( docs.microsoft.com/en-us/dotnet/csharp/nullable-attributes ), необходимые для разработки более сложных вариантов использования, допускающие значение NULL, доступны только в System.Runtime.dll, который поставляется с .NET Core 3.0 и. NET Standard 2.1. Это делает NULL \ C # 8.0 несовместимым с NET Framework 4.8
Виктор Деркс,
3
@BenHall Я добавил несколько выводов из вашей проблемы - большое спасибо за то, что подняли вопрос и разместили здесь. Пожалуйста, не стесняйтесь редактировать ответ, если он неверен.
Стивен Кеннеди
3
Visual Studio 2019 IntelliSense не поддерживает ссылочные типы, допускающие значение NULL, если они указаны <Nullable>enable</Nullable>в csproj. Вроде работает при использовании #nullable enableдиректив. Смотрите также: github.com/dotnet/project-system/issues/5551
Bouke
3
@odalet У меня не было бы никаких проблем с ориентацией на C # 8 и использованием базовых функций, которые не требуют полифиллов (уже делают это), и, возможно, с полифилами тоже (они не нужны). Однако лучший совет, который я могу дать: если сомневаетесь, не делайте этого, по крайней мере, если от этого зависит ваша работа.
Стивен Кеннеди,
34

Согласно этой записи в блоге, язык действительно привязан к фреймворку:

Это означает, что типы, необходимые для использования этих функций, не будут доступны в .NET Framework 4.8. Аналогичным образом, реализации членов интерфейса по умолчанию полагаются на новые усовершенствования среды выполнения, и мы также не будем вносить их в .NET Runtime 4.8.

По этой причине использование C # 8.0 поддерживается только на платформах, реализующих .NET Standard 2.1. Необходимость поддерживать стабильность среды выполнения не позволяла нам реализовывать в ней новые языковые функции более десяти лет. Благодаря параллельному использованию и открытому исходному коду современных сред выполнения, мы чувствуем, что можем снова их развивать и разрабатывать язык с учетом этого. Скотт объяснил в своем «Обновлении по .NET Core 3.0 и .NET Framework 4.8», что в .NET Framework будет меньше инноваций в будущем, вместо этого сосредоточившись на стабильности и надежности. Учитывая это, мы считаем, что лучше упустить некоторые языковые функции, чем никому их получить.

user1781290
источник
3
Еще много подробностей в другом ответе Стивена Кеннеди. Фактически, достаточно легко заставить значительную часть C # 8.0 работать при ориентации на .NET Framework. Но некоторые части C # 8.0 требуют изменений в среде выполнения, которые Microsoft не собирается делать для «старой» .NET Framework. И они, кажется, более тесно связывают языковую версию и версию .NET.
Йеппе Стиг Нильсен
0

C # 8.0 (и выше) поддерживается только в .NET Core 3.x и более новых версиях. Многие из новейших функций требуют функций библиотеки и среды выполнения, представленных в .NET Core 3.x: управление версиями языка C #

Здравко Здравков
источник
3
Вы видели отмеченный как правильный ответ от @stephen kennedy выше?
Джеймс Харкорт,