為什么.NET Standard 仍然有意義?


.NET Standard 是.NET 官方的API規范,可在許多.NET環境中使用。之所以存在,面向.NET Standard 2.0的庫提供了最大可能的覆蓋范圍,並啟用了幾乎所有現代的.NET功能,例如C#9,IAsyncEnumerable等,因此所有庫都應針對該平台。

.NET標准背后的動機是在.NET生態系統中建立更大的一致性。

背景介紹

.NET Framework 很早並且沒有跨平台,.NET Framework發行后,.NET的幾種實現(例如 Mono 和 Unity) 出現在其他平台上,微軟還發布了許多其他實現,例如 UWP, Silverlight和最新的.NET Core, Microsoft重命名為.NET 5的.NET Core是最重要的,因為它是Microsoft真正的.NET跨平台實現,並且Microsoft打算維護該平台。

Microsoft引入了可移植類庫(PCL), 並最終引入了 .NET Standard,以便不同的實現可以共享一組通用的API,這意味着.NET代碼在各個平台之間都是兼容的,並且您可以在任何實現中使用編譯后的代碼。根據Microsoft的說法,.NET Core,.NET 5,.NET Framework,Mono,Xamarin.iOS,Xamarin.Mac,Xamarin.Android,Universal Windows Platform和Unity都以某種方式支持.NET Standard。但是,.NET 5尚未運行所有這些平台。

將來,我們應該會看到.NET 5 正在支持更多的平台,因為Microsoft正在“積極開發”用於iOS和Android等平台的.NET(.NET 5+)。所以:.NET5 是具有統一功能和API的單一產品。

但是,目前,.NET Standard 是兼容大多數.NET 環境的唯一目標,如果要構建在所有這些平台上運行的庫,則需要以.NET Standard 2.0為目標,這是實現的表格以及它們支持的.NET Standard版本

支持.NET Standard 2.0和.NET 5

您可以在.NET Standard 2.0中使用最新的.NET特性,比如 C#9,IAsyncEnumerable ,Span ,System.Text.Json等,這樣的意義在於,這樣做的好處是巨大的,在.NET Framework的項目上也可以使用這些功能。

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFrameworks>netstandard2.0;net5.0</TargetFrameworks>
    <LangVersion>9</LangVersion>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="5.0.0" />
    <PackageReference Include="System.Linq.Async" Version="5.0.0" />
    <PackageReference Include="System.Memory" Version="4.5.4" />
    <PackageReference Include="System.Text.Json" Version="5.0.0" />
  </ItemGroup>

</Project>

下邊是這個庫的一些代碼,它同時支持了.NET Standard 2.0 和.NET 5,但是在一個 .NET Framework的運行項目上使用了這個庫,.NET的新特性仍然可以使用。

using System;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;

namespace DotNetStandardLibrary
{
    public class ExampleClass
    {
        public string Test { get; }

        public ExampleClass(string test)
        {
            Test = test;
        }

        /// <summary>
        /// Uses the Span type
        /// </summary>
        public ExampleClass WriteSpans()
        {
            var spans = new Span<string>(new string[] { "One", "Two" });
            foreach (var span in spans)
            {
                Console.WriteLine(span);
            }

            return this;
        }

        /// <summary>
        /// Use an Async foreach with IAsyncEnumerable
        /// </summary>
        public static async Task DoAsyncNumbersAsync()
        {
            var asyncEnumerable = AsyncEnumerable.Range(0, 10);
            await foreach (var number in asyncEnumerable)
            {
                Console.WriteLine($"Awaited Number: {number}");
            }
        }

        /// <summary>
        /// Serialize and Deserialize with System.Text.Json
        /// </summary>
        public ExampleClass DoSerialize()
        {
            var dailyTemperature = new DailyTemperature(10, 20);
            var json = JsonSerializer.Serialize(dailyTemperature);
            dailyTemperature = JsonSerializer.Deserialize<DailyTemperature>(json);

            if (dailyTemperature == null)
            {
                throw new InvalidOperationException();
            }

            Console.WriteLine($"Json: {json}\r\nHigh: {dailyTemperature.HighTemp} Low: {dailyTemperature.LowTemp}");

            return this;
        }

    }

    public static class Extensions
    {
        /// <summary>
        /// C# Pattern matching example
        /// </summary>
        public static bool IsLetter(this char c) => c is (>= 'a' and <= 'z') or (>= 'A' and <= 'Z');
    }

    /// <summary>
    /// IAsyncDisposable Example
    /// </summary>
    public class AsyncDisposable : IAsyncDisposable
    {
        public ValueTask DisposeAsync() => new ValueTask(Task.FromResult(true));
    }

    /// <summary>
    /// Record example
    /// </summary>
    public record DailyTemperature(double HighTemp, double LowTemp);
}

在.NET Framework 是這樣使用的

using DotNetStandardLibrary;
using System;
using System.Threading.Tasks;

namespace DotNet461ConsoleApp
{
    internal class Program
    {
        private static async Task Main()
        {
            var asyncDisposable = new AsyncDisposable();
            await asyncDisposable.DisposeAsync();

            _ = new ExampleClass("test").WriteSpans().DoSerialize();

            await ExampleClass.DoAsyncNumbersAsync();

            Console.WriteLine($"The character 7 {('7'.IsLetter() ? "is" : "is not")} a letter");
        }
    }
}

總結

.NET Standard可能會部分冗余,但.NET 5目前還不能替代.NET Standard, .NET 5提供了很多新特性,但是,像Unity和Mono這樣的運行時仍然存在,並且在很多地方使用,他們可能會選擇繼續使用它們,而且,.NET Framework上仍然有成千上萬的舊代碼庫,如果目標是.NET Standard 2.0,則保證這些代碼庫可以使用您的庫, 所以.NET Standard還會存在一段時間,並且目前的范圍最廣。

原文作者: Christian Findlay
原文鏈接:https://christianfindlay.com/2020/12/21/net-standard/

最后

歡迎掃碼關注我們的公眾號 【全球技術精選】,專注國外優秀博客的翻譯和開源項目分享,也可以添加QQ群 897216102


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM