C # 8 รองรับ. NET Framework หรือไม่


133

ในการตั้งค่าการสร้างขั้นสูงของ Visual Studio 2019 C # 8 ดูเหมือนจะไม่พร้อมใช้งานสำหรับโครงการ. NET Framework เท่านั้น (ดังภาพด้านล่าง) สำหรับโครงการ. NET Core 3.0:

ใส่คำอธิบายภาพที่นี่

C # 8 รองรับ. NET Framework หรือไม่

คำตอบ:


241

ใช่ 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 เป็นหนทางไปข้างหน้า

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับสิ่งที่ไม่และไม่ทำงานและใน polyfills เป็นไปได้ดูบทความจวร์ตแลงก์, C # 8.0 และ .NET มาตรฐาน 2.0 - ทำสิ่งที่ไม่สนับสนุน


รหัส

โครงการ C # ต่อไปนี้กำหนดเป้าหมาย. NET Framework 4.8 และการใช้ชนิดการอ้างอิงที่เป็นโมฆะ C # 8 คอมไพล์ใน Visual Studio 16.2.0 ฉันสร้างขึ้นโดยเลือกเทมเพลต. NET Standard Class Library จากนั้นแก้ไขเพื่อกำหนดเป้าหมาย. 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รูปแบบเดิมและเพิ่มคุณสมบัติประเภทการอ้างอิงที่เป็นโมฆะเดียวกัน ฉันเปลี่ยนประเภทภาษาในกล่องโต้ตอบการตั้งค่าการสร้างขั้นสูงของ Visual Studio (ปิดใช้งานใน 16.3) เป็นlatestและบันทึกโครงการ แน่นอนว่าจุดนี้มันไม่ได้สร้าง ฉันเปิดไฟล์โครงการในโปรแกรมแก้ไขข้อความและเปลี่ยนlatestเป็นpreviewในการกำหนดค่าการสร้างPropertyGroup:

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

จากนั้นผมก็เปิดใช้งานการสนับสนุนสำหรับประเภทอ้างอิง nullable โดยการเพิ่ม<Nullable>enable</Nullable>การหลักPropertyGroup:

<PropertyGroup>
   <Nullable>enable</Nullable>

ฉันโหลดโครงการซ้ำและสร้างขึ้น


รายละเอียดที่เต็มไปด้วยเลือด

เมื่อคำตอบนี้ถูกเขียนครั้งแรก C # 8 อยู่ในการแสดงตัวอย่างและมีงานนักสืบจำนวนมากที่เกี่ยวข้อง ฉันทิ้งข้อมูลไว้ที่นี่เพื่อลูกหลาน อย่าลังเลที่จะข้ามไปหากคุณไม่จำเป็นต้องรู้รายละเอียดเกี่ยวกับเลือดทั้งหมด

ภาษา C # ในอดีตส่วนใหญ่เป็นเฟรมเวิร์กที่เป็นกลางนั่นคือสามารถรวบรวม Framework เวอร์ชันเก่าได้แม้ว่าคุณลักษณะบางอย่างจะต้องใช้ประเภทใหม่หรือการสนับสนุน CLR ก็ตาม

ผู้ที่ชื่นชอบ C # ส่วนใหญ่จะอ่านรายการบล็อกอาคาร C # 8.0โดย Mads Torgersen ซึ่งอธิบายว่าคุณลักษณะบางอย่างของ C # 8 มีการพึ่งพาแพลตฟอร์ม:

สตรีมตัวสร้างดัชนีและช่วงของ Async ล้วนขึ้นอยู่กับประเภทเฟรมเวิร์กใหม่ที่จะเป็นส่วนหนึ่งของ. NET Standard 2.1 ... .NET Core 3.0 เช่นเดียวกับ Xamarin, Unity และ Mono ทั้งหมดจะใช้. NET Standard 2.1 แต่. NET Framework 4.8 จะ ไม่. ซึ่งหมายความว่าประเภทที่จำเป็นในการใช้คุณสมบัติเหล่านี้จะไม่พร้อมใช้งานบน. NET Framework 4.8

สิ่งนี้ดูเหมือนValue Tuplesซึ่งถูกนำมาใช้ใน C # 7 คุณลักษณะนั้นต้องการประเภทใหม่ - ValueTupleโครงสร้างซึ่งไม่มีใน NET Framework เวอร์ชันที่ต่ำกว่า 4.7 หรือ. NET Standard ที่เก่ากว่า 2.0 อย่างไรก็ตาม , C # 7 ยังสามารถนำมาใช้ในรุ่นเก่าของ .NET อย่างใดอย่างหนึ่งโดยไม่ต้อง tuples ค่าหรือกับพวกเขาโดยการติดตั้งแพคเกจ System.ValueTuple Nuget Visual Studio เข้าใจสิ่งนี้และทุกอย่างก็ดีกับโลก

อย่างไรก็ตาม Mads ยังเขียนว่า:

ด้วยเหตุนี้การใช้ C # 8.0 จึงได้รับการสนับสนุนบนแพลตฟอร์มที่ใช้. NET Standard 2.1 เท่านั้น

... ซึ่งถ้าเป็นจริงจะตัดออกโดยใช้ C # 8 กับ. NET Framework เวอร์ชันใดก็ได้และแม้แต่ในไลบรารี. NET Standard 2.0 ซึ่งเมื่อไม่นานมานี้เราได้รับการสนับสนุนให้ใช้เป็นเป้าหมายพื้นฐานสำหรับรหัสไลบรารี คุณจะไม่สามารถใช้กับ. NET Core เวอร์ชันเก่ากว่า 3.0 ได้เนื่องจากสนับสนุนเฉพาะ. NET Standard 2.0

การสอบสวนดำเนินไปแล้ว! -

  • Jon Skeet มี Noda-Time เวอร์ชันอัลฟ่าที่ใช้ C # 8 พร้อมที่จะไปซึ่งกำหนดเป้าหมาย. NET Standard 2.0 เท่านั้น เขาคาดหวังอย่างชัดเจนว่า C # 8 / .NET Standard 2.0 จะรองรับเฟรมเวิร์กทั้งหมดในตระกูล. NET (ดูบล็อกโพสต์ของ Jon "ขั้นตอนแรกที่มีประเภทการอ้างอิงที่เป็นโมฆะ" )

  • พนักงานของ Microsoft ได้พูดคุยเกี่ยวกับ Visual Studio UI สำหรับประเภทการอ้างอิงที่เป็นโมฆะC # 8 บน GitHubและมีการระบุว่าพวกเขาตั้งใจที่จะสนับสนุนระบบเดิมcsproj(รูปแบบ pre -.NET Core SDK csproj) นี่เป็นข้อบ่งชี้ที่ชัดเจนมากว่า C # 8 จะสามารถใช้งานได้กับ. NET Framework [ฉันสงสัยว่าพวกเขาจะย้อนกลับไปในตอนนี้เนื่องจากมีการปิดใช้งานดรอปดาวน์เวอร์ชันภาษา Visual Studio 2019 และ. NET เชื่อมโยงกับ C # 7.3]

  • ไม่นานหลังจากโพสต์บล็อกที่มีชื่อเสียงเธรด GitHub ได้กล่าวถึงการสนับสนุนข้ามแพลตฟอร์ม จุดสำคัญที่เกิดขึ้นคือ. NET Standard 2.1 จะมีเครื่องหมายที่แสดงว่ารองรับการใช้งานอินเทอร์เฟซเริ่มต้น - คุณลักษณะนี้ต้องการการเปลี่ยนแปลง CLR ที่จะไม่สามารถใช้ได้กับ. NET Framework นี่คือบิตที่สำคัญจาก Immo Landwerth ผู้จัดการโปรแกรมในทีม. NET ที่ Microsoft:

    คอมไพเลอร์ (เช่น C #) คาดว่าจะใช้การมีอยู่ของฟิลด์นี้เพื่อตัดสินใจว่าจะอนุญาตให้ใช้อินเทอร์เฟซเริ่มต้นหรือไม่ หากมีฟิลด์อยู่รันไทม์คาดว่าจะสามารถโหลดและรันโค้ดผลลัพธ์ได้

  • ทั้งหมดนี้ชี้ไปที่ "C # 8.0 ได้รับการสนับสนุนเฉพาะบนแพลตฟอร์มที่ใช้. NET Standard 2.1" ซึ่งเป็นการทำให้เข้าใจง่ายเกินไปและ C # 8 จะรองรับ. NET Framework แต่เนื่องจากมีความไม่แน่นอนมากฉันจึงถาม GitHubและ HaloFour ตอบว่า:

    IIRC คุณลักษณะเดียวที่จะไม่ปรากฏบน. NET Framework อย่างแน่นอนคือ DIM (วิธีการเชื่อมต่อเริ่มต้น) เนื่องจากต้องมีการเปลี่ยนแปลงรันไทม์ คุณสมบัติอื่น ๆ ถูกขับเคลื่อนโดยรูปร่างของคลาสที่อาจไม่ถูกเพิ่มลงใน. NET Framework แต่สามารถเติมแบบ polyfilled ผ่านโค้ดของคุณเองหรือ NuGet (ช่วงดัชนีตัววนซ้ำ async การกำจัดแบบ async)

  • Victor Derks ให้ความเห็นว่า " แอตทริบิวต์ nullable ใหม่ที่จำเป็นในการออกแบบกรณีการใช้งาน nullable ที่ซับซ้อนมากขึ้นมีเฉพาะใน System.Runtime.dll ที่มาพร้อมกับ. NET Core 3.0 และ. NET Standard 2.1 ... [และ] เข้ากันไม่ได้กับ. NET Framework 4.8"

  • อย่างไรก็ตาม Immo Landwerth ให้ความเห็นว่า "API ส่วนใหญ่ของเราไม่จำเป็นต้องมีแอตทริบิวต์ที่กำหนดเองใด ๆ เนื่องจากประเภทเป็นแบบทั่วไปหรือไม่เป็นค่าว่าง" ในบทความลองใช้ประเภทการอ้างอิงที่เป็นโมฆะ

  • Ben Hallยกปัญหาความพร้อมใช้งานของแอตทริบิวต์ที่เป็นโมฆะนอก Core 3.0บน GitHub โดยมีความเห็นต่อไปนี้จากพนักงานของ Microsoft หมายเหตุ:

C # 8 จะรองรับอย่างสมบูรณ์บน. net core 3.0 และ. net มาตรฐาน 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


ข้อแม้ emptor

ชุดค่าผสม C # 8 / .NET Framework ไม่ได้รับการสนับสนุนอย่างเป็นทางการจาก Microsoft พวกเขากล่าวว่าสำหรับผู้เชี่ยวชาญเท่านั้น


3
สิ่งนี้จะช่วยขจัดความสับสนที่เกิดจากความจริงที่เราทำได้หากเราพยายามใช้คุณลักษณะบางอย่างของ C # 8 นอกเหนือจากมาตรฐาน 2.1 - github.com/dotnet/corefx/issues/40039
Ben Hall

2
แอตทริบิวต์ที่เป็นโมฆะใหม่ ( docs.microsoft.com/en-us/dotnet/csharp/nullable-attributes ) ที่จำเป็นในการออกแบบกรณีการใช้งาน nullable ที่ซับซ้อนมากขึ้นจะมีเฉพาะใน System.Runtime.dll ที่มาพร้อมกับ. NET Core 3.0 และ. NET มาตรฐาน 2.1 สิ่งนี้ทำให้ nullable \ C # 8.0 เข้ากันไม่ได้กับ, NET Framework 4.8
Victor Derks

3
@ BenHall ฉันได้เพิ่มประเด็นที่ได้รับจากปัญหาของคุณ - ขอบคุณมากที่แจ้งปัญหาและโพสต์ที่นี่ โปรดอย่าลังเลที่จะแก้ไขคำตอบหากมีวิธีใดไม่ถูกต้อง
Stephen Kennedy

3
Visual Studio 2019 IntelliSense ไม่สนับสนุนชนิดการอ้างอิงที่เป็นโมฆะเมื่อระบุผ่าน<Nullable>enable</Nullable>ในไฟล์csproj. ดูเหมือนว่าจะได้ผลเมื่อใช้#nullable enableคำสั่ง ดูเพิ่มเติมที่: github.com/dotnet/project-system/issues/5551
Bouke

3
@odalet ฉันจะไม่มีความมั่นใจในการกำหนดเป้าหมาย C # 8 และใช้คุณสมบัติพื้นฐานที่ไม่ต้องใช้โพลีฟิลล์ (ทำไปแล้ว) และอาจเป็นไปได้ด้วยโพลีฟิลด้วย (ไม่จำเป็นต้องใช้) อย่างไรก็ตามคำแนะนำที่ดีที่สุดที่ฉันสามารถทำได้คือ: หากมีข้อสงสัยอย่าทำอย่างน้อยก็ไม่ใช่ถ้างานของคุณขึ้นอยู่กับมัน
Stephen Kennedy

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 จะเห็นนวัตกรรมน้อยลงในอนาคตแทนที่จะเน้นที่ความเสถียรและความน่าเชื่อถือ ด้วยเหตุนี้เราจึงคิดว่ามันเป็นการดีกว่าที่จะพลาดคุณสมบัติทางภาษาบางอย่างมากกว่าที่จะไม่มีใครได้รับ


3
รายละเอียดเพิ่มเติมอีกมากมายในคำตอบอื่น ๆ โดย Stephen Kennedy ในความเป็นจริงมันง่ายพอที่จะทำให้ชุดย่อยของ C # 8.0 ทำงานได้เมื่อกำหนดเป้าหมาย. NET Framework แต่บางส่วนของ C # 8.0 ต้องการการเปลี่ยนแปลงรันไทม์ซึ่ง Microsoft จะไม่สร้างให้กับ. NET Framework "เก่า" และดูเหมือนว่าพวกเขาจะผูกเวอร์ชันภาษากับเวอร์ชัน. NET เข้าด้วยกันมากขึ้น
Jeppe Stig Nielsen

1

C # 8.0 (และสูงกว่า) รองรับเฉพาะบน. NET Core 3.x และเวอร์ชันที่ใหม่กว่า คุณลักษณะใหม่ล่าสุดจำนวนมากต้องการคุณสมบัติไลบรารีและรันไทม์ที่นำมาใช้ในการกำหนดเวอร์ชันภาษา . NET Core 3.x: C #


3
คุณเห็นคำตอบที่ทำเครื่องหมายว่าถูกต้องจาก @stephen kennedy ด้านบนหรือไม่?
James Harcourt
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.