• 为什么.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}
    High: {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

  • 相关阅读:
    python入门1
    查找字段 和查找组件
    DBGRID 拖动滚动条 和 鼠标滚轮的问题
    数据集 过滤时 RecordCount 属性
    查找字段 如何 过滤
    数据集控件 放在 数据模块 上后,如何写事件代码
    取TTable 过滤后的记录数
    判断 Windows操作系统是32位还是64位
    MatchText MatchStr 区别
    EClassNotFound
  • 原文地址:https://www.cnblogs.com/myshowtime/p/14277993.html
Copyright © 2020-2023  润新知