来自后端的突袭? --开包即食的教程带你浅尝最新开源的C# Web引擎 Blazor

在今年年初, 恰逢新春佳节临近的时候. 微软给全球的C#开发者们, 着实的送上了一分惊喜. 微软正式开源Blazor ,将.NET带回到浏览器.

这个小惊喜, 迅速的在dotnet开发者中间传开了. 而就在昨天(2018年3月22日) Blazor发布了它的第一次Release. Blazor到底是个什么样的东西呢?我们是否真的可以携着C#语言进入前端的市场中? 不如现在就跟我一起体验dotnet blazor吧.

首先

获取最新版的dotnet core 并安装Blazor模板:

  • 安装 最新的.Net Core(版本需要高于2.1.101)

  • 对于简单的尝试来说, VS code 已经足够. 所以笔者并没有亲自安装Visual Studio.

使用命令行初始化项目:

dotnet new -i Microsoft.AspNetCore.Blazor.Templatesdotnet new blazor -o BlazorApp1cd BlazorApp1dotnet run

 

  • 如果你需要使用Visual Studio,

    • 安装最新的Visual Studio 2017.

    • 安装 ASP.NET Core Blazor Language Services extension

    • 在Visual Studio中创建新的测试项目:

    • 选择 File -> New Project -> Web -> ASP.NET Core Web Application

    • 确定在Target Framework里选择了 .NET Core and ASP.NET Core 2.0.

    • 选择 Blazor 模板

敌后根据地? 如何在前端渲染cshtml

当我们运行起项目之后, 就可以看到如下提示


个时候我们在浏览器里打开监听的端口 http://localhost:17477. 就可以看到我们这个项目的网页了.

这个简单的示例项目带了3个页面

 第一个页面比较简单, 但先别急,让我们打开浏览器工具. 先看看页面在加载页面过程中都加载了什么

在初次打开页面的时候, 我们看到的是这样一个Loading..的页面.  这个页面的代码是这样的.


<!DOCTYPE html><html><head><meta charset="utf-8" /><title>BlazorDemo</title><base href="/" /><link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" /><link href="css/site.css" rel="stylesheet" /></head><body><app>Loading...</app><script src="css/bootstrap/bootstrap-native.min.js"></script><script src="_framework/blazor.js" main="BlazorDemo.dll" entrypoint="BlazorDemo.Program::Main" references="Microsoft.AspNetCore.Blazor.Browser.dll,Microsoft.AspNetCore.Blazor.dll,Microsoft.Extensions.DependencyInjection.Abstractions.dll,Microsoft.Extensions.DependencyInjection.dll,mscorlib.dll,netstandard.dll,System.Core.dll,System.Diagnostics.StackTrace.dll,System.dll,System.Globalization.Extensions.dll,System.Net.Http.dll,System.Runtime.Serialization.Primitives.dll,System.Security.Cryptography.Algorithms.dll" linker-enabled="true"></script></body></h可以看到这个页面加载了两个js, 第一个是bootstrap的, 第二个叫做blazor.js. 只不过这个js有非常多的参数, 有 main, entrypoint, 和 references. 看看References里写的是不是很熟悉? 一看就是.netdll.

blazor.js 加载了mono.js, mono.js 加载了mono.wasm. 这个是个什么文件?


asm代表的就是Web Assembly, 简单地说它就是编译好的二进制文件, 可以由浏览器直接运行, 源语言可以是C/C++或者任何可以编译到Web Assembly的文件, 而这里我们加载的就是mono 编译好的Web Assembly文件, 它被加载之后, 相当于浏览器中启动了一个mono 运行环境.

随后的两个js 是笔者chrome浏览器插入的js, 在这里不要被他们干扰了. 那么mono 运行时加载完成之后. 就需要加载dotnet 的Dll了, 首先是入口库, 接着就是需要的引用库

好家伙 1.9MB. 当所有的Dll被下载完毕之后, 这个时候我们的浏览器就可以运行我们这个dotnet的网页了. 于是就回到了我们最开始看到的那个应用程序.

所以 总结一下 blazor.js 调用mono.js, mono.js加载mono.wsam, 然后根据写在script标签里的内容继续的加载dotnet的库文件. 如果浏览器不支持wsam, 就会尝试使用asm.js加载mono.asm.js

柳暗花明又一村,Blazor的模板究竟是怎样的.

我们已经知道,经过前面的步骤,浏览器里已经运行了一个.Net 运行时了. 而且加载了项目必须的dll. 那么这样一个简单的程序,它的代码究竟是怎么样的呢? 

打开项目代码,映入眼帘的是一个标准的.net Project

_ViewImports.cshtml包含了项目一些其他页面中最常使用的namespace

5


7

@using System.Net.Http

@using Microsoft.AspNetCore.Blazor

@using Microsoft.AspNetCore.Blazor.Components

@using Microsoft.AspNetCore.Blazor.Layouts

@using Microsoft.AspNetCore.Blazor.Routing

@using BlazorDemo

@using BlazorDemo.Shared

 

Program.cs是程序的入口点

using Microsoft.AspNetCore.Blazor.Browser.Rendering;

using Microsoft.AspNetCore.Blazor.Browser.Services;

using System;


namespace BlazorDemo

{

    class Program

    {

        static void Main(string[] args)

        {

            var serviceProvider = new BrowserServiceProvider(configure =>

            {

                // Add any custom services here

            });


            new BrowserRenderer(serviceProvider).AddComponent<App>("app");

        }

    }

}

在入口点中, 我们注册了一个浏览器渲染服务 BrowserRender,让他渲染App

App.cshmtl是这样的

<Router AppAssembly=typeof(Program).Assembly />

这里的Router对应的是Microsoft.AspNetCore.Blazor.Routing.Router. 当给它一个AppAssembly时, 他就会自动的把当前的Url 和 AppAssembly的其他Pages对应起来.

所以 当我们在浏览器里输入 /Counter时,他就会加载Pages/Couter.cshtml.

Shared文件夹里分别是布局文件,导航栏, 还有一个我们自定义的控件 SurveyPrompt. 

熟悉Razor引擎的小伙伴们一定很轻车熟路了. 那么当我们打开网站时, 默认显示给我们的 就是Index, 这个时候我们会加载Pages/Index.cshtml

Index.cshtml的代码是这个样子的

@page "/"<h1>Hello, world!</h1>Welcome to your new app.
<SurveyPrompt Title="How is Blazor working for you?" />

@page 可以告诉Router, 当前页面注册到 "/"

除了显示hello world以外, 我们在这里还看到了刚刚说到的第三方控件. SurveyPrompt. 果然不简单嘛, 一个看似简单的页面, 居然还告诉了我们如何使用自定义控件.

从声明上看, 我们知道 SunveyPrompt是一个控件,并且有一个属性Title. 现在我们打开它的代码

<div class="alert alert-survey" role="alert">

    <span class="glyphicon glyphicon-ok-circle" aria-hidden="true"></span>

    <strong>@Title</strong>


    Please take our

    <a target="_blank" class="alert-link" href="https://go.microsoft.com/fwlink/?linkid=870381">

        brief survey

    </a>

    and tell us what you think.

</div>

@functions

{

    // This is to demonstrate how a parent component can supply parameters

    public string Title { get; set; }

}

我们可以看到代码分为两部分, @functions上面是类似html的东西, 下面是类似C#的东西. 熟悉React或者Vue的伙伴们恐怕不会对这种混写感到陌生. 这个就是Blazor的语法. Html部分很像使Razor的模板方式. 而最后整个页面都会被编译成一个类, 这个类派生自 Component. 如果你编译过项目, 你会在Debug下面的Shared目录找到一个叫SurveyPrompt.g.cs的东西

#pragma checksum "/Users/pzhi/SCM/gitHub/zhipu123/BlazorDemo/Shared/SurveyPrompt.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "a2a2ea88635b799343bc6d9647bbb818c8a20c9d"

// <auto-generated/>

#pragma warning disable 1591

namespace BlazorDemo.Shared

{

    #line hidden

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Threading.Tasks;

    using System.Net.Http;

    using Microsoft.AspNetCore.Blazor;

    using Microsoft.AspNetCore.Blazor.Components;

    using Microsoft.AspNetCore.Blazor.Layouts;

    using Microsoft.AspNetCore.Blazor.Routing;

    using BlazorDemo;

    using BlazorDemo.Shared;

    public class SurveyPrompt : Microsoft.AspNetCore.Blazor.Components.BlazorComponent

    {

        #pragma warning disable 1998

        protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)

        {

            base.BuildRenderTree(builder);

            builder.OpenElement(0, "div");

            builder.AddAttribute(1, "class", "alert alert-survey");

            builder.AddAttribute(2, "role", "alert");

            builder.AddContent(3, "\n    ");

            builder.OpenElement(4, "span");

            builder.AddAttribute(5, "class", "glyphicon glyphicon-ok-circle");

            builder.AddAttribute(6, "aria-hidden", "true");

            builder.CloseElement();

            builder.AddContent(7, "\n    ");

            builder.OpenElement(8, "strong");

            builder.AddContent(9, Title);

            builder.CloseElement();

            builder.AddContent(10, "\n\n    Please take our\n    ");

            builder.OpenElement(11, "a");

            builder.AddAttribute(12, "target", "_blank");

            builder.AddAttribute(13, "class", "alert-link");

            builder.AddAttribute(14, "href", "https://go.microsoft.com/fwlink/?linkid=870381");

            builder.AddContent(15, "\n        brief survey\n    ");

            builder.CloseElement();

            builder.AddContent(16, "\n    and tell us what you think.\n");

            builder.CloseElement();

            builder.AddContent(17, "\n\n");

        }

        #pragma warning restore 1998

        

    // This is to demonstrate how a parent component can supply parameters

    public string Title { get; set; }

    }

}

#pragma warning restore 1591

我们发现@functions里面的内容 会作为这个类的成员变量和 成员方法, 而上面的内容则被编译到了BuildRenderTree方法中.

那么到了这里我们大概知道了这个简单的HomePage都有什么玄机了. 我们也大概知道了Blazor的语法, 也知道其实我们所有的页面最终都会是一个Componet.

那么什么是Componet呢? 在这里并不想过多的去笔墨介绍这个概念. 如果你是一个Vue或者React的开发, 你应该对这个模块化开发不陌生. 一个Componet, 就是满足一定的功能, 有自己的属性, 状态. 可以展示特定数据的元素.

就如同我们这里的SurveyPrompt, 接受一个Title属性,并且负责把他展示成这样子

 数据驱动? Blazor的刷新和绑定机制初探

现在我们知道了一个简单的页面是如何渲染出来的. 那么让我们打开Counter这个配置来看一看. 数据是如何交互的

我们第二个page张这样子

有一个button, 大声的叫我们点它. 当我们点击的时候. 上面的current count 变成了 1

 

这一切是怎么发生的呢? 以下是Counter.cshtml的代码

@page "/counter"

<h1>Counter</h1>


<p>Current count: @currentCount</p>


<button @onclick(IncrementCount)>Click me</button>


@functions {

    int currentCount = 0;


    void IncrementCount()

    {

        currentCount++;

    }

}

 我们看到 这个页面非常简单, 我们定义了一个CurrentCount的Field, 然后在IncreaseCount方法里给它加一. 一个叫Click me的button标签里 有一个@onclick方法, 将IncreaseCount作为参数

Counter.cshtml编译后的代码张这样

#pragma checksum "/Users/pzhi/SCM/gitHub/zhipu123/BlazorDemo/Pages/Counter.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "05ad2dd449cbc9f09f8b759e1f06e7eb5e9583b4"

// <auto-generated/>

#pragma warning disable 1591

namespace BlazorDemo.Pages

{

    #line hidden

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Threading.Tasks;

    using System.Net.Http;

    using Microsoft.AspNetCore.Blazor;

    using Microsoft.AspNetCore.Blazor.Components;

    using Microsoft.AspNetCore.Blazor.Layouts;

    using Microsoft.AspNetCore.Blazor.Routing;

    using BlazorDemo;

    using BlazorDemo.Shared;

    [Microsoft.AspNetCore.Blazor.Layouts.LayoutAttribute(typeof(MainLayout))]

    [Microsoft.AspNetCore.Blazor.Components.RouteAttribute("/counter")]

    public class Counter : Microsoft.AspNetCore.Blazor.Components.BlazorComponent

    {

        #pragma warning disable 1998

        protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)

        {

            base.BuildRenderTree(builder);

            builder.OpenElement(0, "h1");

            builder.AddContent(1, "Counter");

            builder.CloseElement();

            builder.AddContent(2, "\n\n");

            builder.OpenElement(3, "p");

            builder.AddContent(4, "Current count: ");

            builder.AddContent(5, currentCount);

            builder.CloseElement();

            builder.AddContent(6, "\n\n");

            builder.OpenElement(7, "button");

            builder.AddAttribute(8, onclick(IncrementCount));

            builder.AddContent(9, "Click me");

            builder.CloseElement();

            builder.AddContent(10, "\n\n");

        }

        #pragma warning restore 1998

        

    int currentCount = 0;


    void IncrementCount()

    {

        currentCount++;

    }

    }

}

#pragma warning restore 1591

我们看到 @onclick其实在这里就是执行了一个Component的一个方法onclick, 顾名思义,当这个Component被点击的时候就被调用. 我们的IncreaseCount被作为参数传给了它, 可见onclick会在被点击的时候执行IncreaseCount.

那么问题来了,当我们执行了IncreaseCount方法时, 页面怎么会知道要不要刷新? 是刷新整个页面还是刷新所有?

熟悉WPF的同学可能知道, 在WPF中如果我们需要让一个ViewModel可以被监听变化, 他就需要实现INotifyChanged事件. 那么同样道理, 我们的这个IncreaseCount可能也是类似的吗?

然而基于编译后的代码我们可以发现 CurrentCount作为我们Counter这个类的Field, 并没有任何机会高速Page自己变化了. 而且这个Field非常普通,也不是什么WPF中的DP, 所以到目前为止变化是怎么通知的.并没有一个合理的解释. 后面的时间里我会尝试阅读Blazor的代码搞清楚这件事情. 

第一个问题画个问号, 那么第二个问题呢? 

打开浏览器工具, 定位到button, 再次点击button观察dom的反应.

我们看到 在点击Button的时候, button上面的<p>标签闪动了, 说明它被刷新了, 而其他标签并没有. 所以局部刷新的功能是有的. 效率问题不用担心了. 

编辑Click me, 把他的内容变成 "点击我", 再次点击按钮, 我们看到还是只有p变, 而且button也没有变回原来的内容

 

 所以我们知道, 这个局部刷新不是简单的拿Dom作比较, 肯定是有Virtual Dom的机制在里面.

 

 星星之火,可燎原?

在简单的尝试了Blazor之后, 还是很兴奋的. 可以看到Blazor是一个初具规模的产品. 我们C#开发可以用Blazor在今后写前端渲染的网页了! 

我很期望这样一个产品能够持续的演进下去.

就目前版本看(0.1.0), Blazor尚不能应用到产品中. 主要还是有以下的原因

  •  打包大小太大, 1.8M的大小对于网站简直是致命的.

  •  产品还不成熟, 现在Component还只能支持简单的事件, 笔者测试的时候只有onclick,onchange. 

  •  兼容性差,使用了WebAssembly,就注定了两年前的浏览器必定不能支持.

当然我们还是不能否认, Blazor为如何让更多语言进入前端世界打开了一扇新的大门. 也许未来JavaScript将不仅仅是前端唯一可以使用的利器. 我们会看到C/C++, Python, Java写的前端渲染页面也不一定呢.

当然在后端语言打入前端世界的道路上, WebAssembly也未必是唯一的路劲, 比如Scala.js就完全使用了js重写了Scala的库函数, 类似的还有Kotlin.js. 可以看到虽然JavaScript已经非常Fancy了,但是后端程序员们进军前端的热情可谓从未停歇过啊.

祝dotnet的应用越来越广, 祝广大后端程序员们新年成就慢慢, 加薪升职.

原文: https://www.cnblogs.com/Gerryz/p/get-start-with-dotnet-blazor.html 


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/321863.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

博客文章列表(二)——算法、数据结构、数据库、ABCD

七、编程基础 数据结构 详情列表 算法 详情列表 算法.排序 详情列表 算法.加密 详情列…

A*B NTT快速数论变换

wmq的AB Problem 发布时间: 2017年4月9日 17:06 最后更新: 2017年4月9日 17:07 时间限制: 3000ms 内存限制: 512M 描述 这是一个非常简单的问题。 wmq如今开始学习乘法了&#xff01;他为了训练自己的乘法计算能力&#xff0c;写出了n个整数&#xff0c;并且对每两个数a,…

51nod-猴猴吃苹果【线段树】

正题 题目链接:https://www.51nod.com/Contest/ProblemList.html#contestId188&randomCode291765 题目大意 nnn个点的一棵树&#xff0c;从kkk节点出发&#xff0c;每次走到最远的一个节点(路上点最多,如果有多个就编号最小的)并将路上的点权变为0&#xff0c;求会依次到达…

北方大学 ACM 多校训练赛 第十五场 蜘蛛牌A

题目描述 XCX最近迷上了玩蜘蛛牌。蜘蛛牌是windowsxp操作系统自带的一款纸牌游戏&#xff0c;游戏规则是这样的&#xff1a;只能将牌拖到比它大一的牌上面&#xff08;A最小&#xff0c;K最大&#xff09;&#xff0c;如果拖动的牌上有按顺序排好的牌时&#xff0c;那么这些牌也…

dotnet watch+vs code提升asp.net core开发效率

在园子中&#xff0c;已经又前辈介绍过dotnet watch的用法&#xff0c;但是是基于asp.net core 1.0的较老版本来讲解的&#xff0c;在asp.net core 2.0的今天&#xff0c;部分用法已经不太一样&#xff0c;所以就再写一篇文章来介绍dotnet watch vs code来提升asp.net core开发…

51nod-猴猴吃香蕉【dp】

正题 题目链接:https://www.51nod.com/Contest/Problem.html#contestProblemId1149 题目大意 nnn个数&#xff0c;求有多少种选择方案使选择的数乘机为kkk。 解题思路 显然kkk的质因数最多只有999个&#xff0c;我们将质因数进行dpdpdp。若选择的数的质因数刚好是kkk的质因数…

北方大学 ACM 多校训练赛 第十五场 数字游戏

本题的意思是&#xff0c;给你1/2&#xff0c;1/2&#xff0c;1&#xff0c;2&#xff0c;4……2^&#xff08;k-1&#xff09; &#xff0c;让你在左边的数列中添加号或者-号&#xff0c;使得最终的答案为n即可。 思路&#xff1a; 我们知道上面这些数直接如果全部都填号的话…

ASP.NET Core + Docker + Jenkins + gogs + CentOS 从零开始搭建持续集成

没有采用gitlab&#xff0c;因为gitlab比较吃配置。也比较重&#xff0c;用不到那么多功能。采用go语言开发的gogs来代替。免费HTTPS证书安装Gogs (一个gitserver&#xff0c;类似于gitlab)安装DockerDocker配置加速器 一定要配置&#xff0c;用官方的源会让你体会到什么叫做绝…

51nod-猴猴的比赛【莫队,线段树】

正题 题目链接:https://www.51nod.com/Contest/Problem.html#contestProblemId1150 题目大意 给出两颗nnn个点的树&#xff0c;求有多少个点(i,j)(i,j)(i,j)对使得在两棵树中iii都是jjj的祖先。 解题思路 在dfsdfsdfs序中一个节点的孩子是在一个连续的区间中的。所以对于第一…

北方大学 ACM 多校训练赛 第十五场 买花

显然是一个比较简单的离线查询问题。 本质上是对区间求集合的问题&#xff0c;按照区间右端点从小到大对区间进行排序&#xff0c;然后用一个指针curr表示当前正在考虑区间的最右侧位置&#xff0c;针对排好序区间[tarl,tarr]&#xff0c;先查看curr是否到达tarr&#xff0c;如…

使用CoreRT将.NET Core发布为Native应用程序

在上一篇文章《使用.NET Core快速开发一个较正规的命令行应用程序》中我们看到了使用自包含方式发布的.NET Core应用中包含了216个文件。我就写一个cat命令用得着这么动真格。。。这写出来的命令行还有人用吗&#xff1f;今天我们就来介绍一下MS的另一个开源项目CoreRT。用来解…

P4343-[SHOI2015]自动刷题机【二分答案】

正题 题目链接:https://www.luogu.org/problem/P4343 题目大意 nnn个操作每个操作加几行代码或减几行代码&#xff0c;若代码积累到xxx行就自动删除所有代码并切掉一道题。 已知道切掉了kkk题&#xff0c;求最大和最小的xxx 解题思路 因为xxx和切题的数量单调&#xff0c;所…

北方大学 ACM 多校训练赛 第十五场 欢度6.18

把式子变成a[i]1 p(a[i-1]1)q[a[i-2]1]&#xff0c;矩阵快速幂搞定。复杂度o(logn) #include <iostream> #include <cstdio> using namespace std; #define int long long int x,y,p,q,n; const int MOD 1000000007;int fast_mod(int n) // 求 (t^n)%MOD {i…

.NET Core 2.1预览版首次引入Global Tools

Global Tools是.NET Core 2.1预览版中其中一个初次出现的特性。Global Tools提供了一种方法&#xff0c;让开发人员编写的.NET Core应用可以打包成NuGet包交付。如果.NET Core运行在目标平台上&#xff0c;那么一个恰当打包的Global Tool就可以在那上面运行。JavaScript开发人员…

P5253-丢番图【数论】

正题 题目链接:https://www.luogu.org/problem/P5253 题目大意 给一个nnn&#xff0c;求有多少对x,y(x≤y)x,y(x\leq y)x,y(x≤y)使得 1x1y1n\frac{1}{x}\frac{1}{y}\frac{1}{n}x1​y1​n1​ 解题思路 xyxy1n\frac{xy}{xy}\frac{1}{n}xyxy​n1​ n(xy)xyn(xy)xyn(xy)xy xy−n…

最小费用购物问题

西安交大 软件53 蔡少斐 题号&#xff1a;3_14 题目叙述&#xff1a; 某商店中每种商品都有一个价格。例如&#xff0c;一朵花的价格是2 ICU(ICU 是信息学竞赛的货币的单位&#xff09;;一个花瓶的价格是5 ICU。为了吸引更多的顾客&#xff0c;商店提供了特殊优惠价。 特殊优…

开源服务容错处理库Polly使用文档

在进入SOA之后&#xff0c;我们的代码从本地方法调用变成了跨机器的通信。任何一个新技术的引入都会为我们解决特定的问题&#xff0c;都会带来一些新的问题。比如网络故障、依赖服务崩溃、超时、服务器内存与CPU等其它问题。正是因为这些问题无法避免&#xff0c;所以我们在进…

P2638-安全系统【数论,组合数学】

正题 题目链接:https://www.luogu.org/problem/P2638 题目大意 aaa个不同的000&#xff0c;bbb个不同的111。nnn个位置每个可以放0,10,10,1可以都放也可以不放也可以只放一个。然后求方案数。 解题思路 答案就是(∑i0aCni∗Cai)∗(∑i0bCni∗Cbi)(\sum_{i0}^a C_{n}^{i}*C_{a…

宝石排列问题

西安交大 软件53 蔡少斐 题号&#xff1a;5_10 题目叙述&#xff1a; 现有n种不同形状的宝石&#xff0c;每种n颗&#xff0c;共n*n颗。同一形状的n颗宝石分别具有n种不同的颜色c1,c2,…,cn中的一种颜色。欲将这n*n颗宝石排列成n行n列的一个方阵&#xff0c;使方阵中每一行…

大部分Intel hardware intrinsic 将在 .NET Core 2.1 中启用

编者注&#xff1a;SIMD via C# 引入了一套全新的机制&#xff0c;使得C# 以后可以像C/C 一样直接使用intrinsic functions 来直接操作Intel CPU 的大多数SIMD 指令了&#xff08;从SSE 到AVX2&#xff09;随着 .NET Core 2.1 发布的临近&#xff0c;上周CoreCLR 已经停止向mas…