C#语法糖系列 —— 第四篇:聊聊 Span 的底层玩法

把 Span 归于语法糖,可能有些偏了,但偏了就偏了,哈哈,只要是分享就好,C# 发展至今,已经是一门非常重的语言了,所有想要的它都要,即可以:

  1. 面向过程编程

  2. 面向对象编程

  3. 面向函数式编程

  4. 面向异步编程

  5. 面向泛型编程

既能做到 高开发效率 ,又能做到 高性能编程

这里的 Span 就归结于 高性能编程 这个范畴了。

一:Span 是什么

当年的 C# 一个亮点就是屏蔽了指针,自动内存托管,可以让程序员更加专注于业务,现如今策略变了,C# 要变得更加高性能,既然要做高性能那必然少不了指针,而指针又是面向 托管层 编程的程序员最怕的东西,所以就尽可能的封装,弄一套属于自己的托管指针玩法。

Span 即属于托管指针玩法 的一个典型代表,如果你用 ILSpy 去看它的 struct 结构,本质上就两个成员,一个叫 _pointer,一个叫 _length,参考如下代码:

public readonly ref struct Span<T>{internal readonly ByReference<T> _pointer;private readonly int _length;}

pointer 是 指定起点, length 是 控制边界,如果用 C 来模拟,大概就是这个样子。

struct Span {void* ptr;int length;
};

画个图大概就是这样子。

69687a04cd8f259b15aae864d119456e.png

二:Span 的场景在哪里

有了指针,就可以对 内存 进行原地操作,只要能 原地操作 ,那就可以破掉 语言层面 上的诸多限制,实现接近 C/C++ 级的高性能,有些朋友可能要问了,语言层面有什么限制?比如最典型的 string ,大家都知道 string 是一个 writeoncopy 特性的字符串,只要你动它一下,它就会繁殖,接下来我们就拿 string 举个例子。

1. string 中的数字求 sum

在很久以前你可能会这么做。

static void Main(string[] args){var s = "97 3";var arr = s.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);var sum = Convert.ToInt32(arr[0]) + Convert.ToInt32(arr[1]);Console.WriteLine(sum);}
b230b38b7d9b53963436ecb2c0db9583.png

从代码可以看出,对 string 进行 Split 会导致生成多个小 string 对象,那有没有办法不用生成小string呢?这就需要用到托管版的 Span 做原地处理了。

static void Main(string[] args){var s = "97 3";var position = s.IndexOf(' ');ReadOnlySpan<char> span = s.AsSpan();var num1 = int.Parse(span.Slice(0, position));var num2 = int.Parse(span.Slice(position));Console.WriteLine(num1 + num2);}
1f99dcbe58d4c460fdc98b94f3dc42ba.png

Span 的这种做法就是通过 _pointer 指针在内存地址上进行移动来完成,如果看不明白,我可以用 C 来模拟一下。

#include <iostream>struct Span {int length;void* ptr;
};void sum(Span* span);int main()
{Span span;span.ptr = (char*)"97 3";span.length = strlen((char*)span.ptr);sum(&span);
}void sum(Span* span) {int sum = 0;char* position = strchr((char*)span->ptr, ' ');Span span1;span1.ptr = span->ptr;span1.length = (position - span->ptr) / sizeof(char);Span span2;span2.ptr = position;span2.length = span->length - span1.length - 1;int num1= atoi((char*)span1.ptr);int num2= atoi((char*)span2.ptr);sum = num1 + num2;printf("sum=%d", sum);
}
092babf5735de0062e40d6ca9e2a7ffb.png

虽然代码有点多,但逻辑还是很清楚的。

如果大家明白 Span 所封装的底层指针玩法,我想这其实没什么难的,本篇就说到这里吧,希望对你有帮助。

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

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

相关文章

【ArcGIS风暴】河流水系左斜体样式经典设置方法

目录 一、效果预览 二、实现方法 一、效果预览 河流水系在作图时一般设置为左斜体、蓝色,如黄河、青海湖、洮河等,如下图所示: 二、实现方法 下面介绍在ArcGIS 10.5中的实现方法。 1、ArcGIS设置方法 绘图工具添加文字或者将标注转为注记,双击,打开属性,点击更改符号…

HBase简介(很好的梳理资料)

HBase HBaseHadoop网络应用数据结构NoSQL 一、 简介 history started by chad walters and jim 2006.11 G release paper on BigTable 2007.2 inital HBase prototype created as Hadoop contrib 2007.10 First useable Hbase 2008.1 Hadoop become Apache top-level project …

python 实现原型设计模式

原型设计模式主要在当新建一个对象的时候&#xff0c;觉得很麻烦&#xff0c;并且你又要保留当前对象。在这种情况下使用原型设计模式是一个很好的解决办法。 例如你写一个东西更新&#xff0c;不同的版本&#xff0c;这个时候以前的版本肯定要保留&#xff0c;并且从此基础上…

装服务器显示磁盘脱机,服务器磁盘处于脱机

服务器磁盘处于脱机 内容精选换一换配置目的端或启动目的端时提示“SMS.1311 目的端磁盘个数不够”。在配置目的端服务器过程中&#xff0c;会校验目的端磁盘数量是否和源端一致。当出现该错误时&#xff0c;检查目的端服务器磁盘数量是否少于源端服务器磁盘数量&#xff0c;或…

剑指offer之重建二叉树

1 问题 重建二叉树&#xff1a;给定二叉树的先序遍历&#xff08;根左右&#xff09;和中序&#xff08;左中右&#xff09;遍历结果&#xff0c;建立这棵二叉树。输入保证二叉树无重复结点 以先序{1, 2, 4, 7, 3, 5, 6, 8}和中序{4, 7, 2, 1, 5, 3, 8, 6}为例 2 分析 先序遍…

ArcGIS 10.5专题地图制作自定义漂亮图框

先来看一下效果: 下面来说明如何在ArcGIS软件里面实现自定义图框。 1. 【自定义】→【样式管理器】→【Administrator.style】→【边框】→【新建】→【常规边框】。 2. 点击【更改符号】。 3. 点击【编辑符号】。

当我会AOP之后,去丈母娘家都是挺着胸脯!

当和朋友谈到AOP时&#xff0c;第一映像会说AOP的应用层面&#xff0c;比如拦截器、过滤器&#xff0c;实现复用等等使用层面上。这些应用层面上的回答远远没有深入AOP的思想。是的&#xff0c;AOP是思想&#xff0c;面向切面思想。既然是编程思想&#xff0c;那我们就有必要了…

python 最简单的实现适配器设计模式

适配器设计模式是懒得改动某些代码&#xff0c;或者某些接口不方便改动的时候&#xff0c;使用一个特定的封装&#xff0c;一些特定的编写办法&#xff0c;使不同的接口可以使用同种调用方式使用。 更简单的说话则是&#xff0c;例如几个不同的接口 aliyun、qiniuyun、tencent…

Envi和ArcGIS软件打开和处理.NC4数据

NC4是NetCDF-4的简缩形式。 NetCDF(network Common Data Form)网络通用数据格式是由美国大学大气研究协会(University Corporation for Atmospheric Research,UCAR)的Unidata项目科学家针对科学数据的特点开发的,是一种面向数组型并适于网络共享的数据的描述和编码标准。目…

C#多线程调试

概要这篇文章主要分享多线程部分调试技巧&#xff0c;在日常的开发工作中会经常遇到多线程调试的需要。在我们调试的过程中会出现断点的焦点在多个线程之间“反复横跳”根本无法集中跟踪某一个线程的操作链路。那么今天我们来看看如何调试操作。如果有其它需要的可以参考下面微…

最速下降法(梯度下降法)

最速下降法的影子在机器学习中正是无处不在&#xff0c;它简单实用。 一、表示 在最速下降法中&#xff0c;对权值向量w的连续调整是在最速下降的方向上&#xff0c;即它是与梯度向量方向相反的&#xff0c;梯度向量记为&#xff08;1&#xff09;&#xff0c;简记&#xff08;…

游戏服务器销售额,游戏服务器销售一个月

游戏服务器销售一个月 内容精选换一换应用容器化改造有三种方式&#xff0c;您可单击这里查看。本教程以某游戏为例&#xff0c;将该游戏进行微服务的架构改造&#xff0c;再进行容器化。本教程不对改造细节做深度讲解&#xff0c;仅讲解大致的建议。如需要详细了解容器化改造的…

使用AppCompat项目模版

2019独角兽企业重金招聘Python工程师标准>>> 使用AppCompat项目模版 从Android API 22开始&#xff0c;谷歌推荐使用AppCompatActivity来构建带标题栏的App&#xff0c;而不是原有的ActionBarActivity。如果用户想要使用AppCompatActivity&#xff0c;可以使用Xamar…

python3 最基本且简单的实现组合设计模式

组合模式是把一个类别归为一个整体&#xff0c;并且组织多个整体之间的关系&#xff0c;使用通过树形结构来描述所有整体。 一般的编写方式为一个类别对象下添加多个该对象的元素&#xff0c;该对象又为其它对象下的元素。简单来说就是一个学校有一个总部&#xff0c;总部下有…

SQL Server 2008 阻止保存要求重新创建表的更改问题

习惯了使用SQL Server 2005进行数据库系统开发,为了赶上潮流的发展,最近在使用SQL 2008数据库,本来建好了一个表,后面需要对表的设计做些修改(比如字段长度的修改,忘记了设置主键等等),结果弹出错误提示,说什么“组织保存要求重新创建表的更改”,如下所示: 解决办法…

$geoNear

怎么使用mongoose的geoNear 2014-11-26 15:05:20| 分类&#xff1a; mongodb | 标签&#xff1a;mongoose |举报|字号 订阅 下载LOFTER我的照片书 |起因 在开发的时候碰到一个情况&#xff0c;数据源有100个景点&#xff0c;需要对给出的一个点&#xff0c;求距离它最近的…

甲骨文宣布供应链管理云平台支持LogFire仓库管理系统

本文讲的是 :甲骨文宣布供应链管理云平台支持LogFire仓库管理系统 ,【IT168 资讯】甲骨文发布了一系列对其供应链管理产品的更新&#xff0c;并表示&#xff0c;云平台现在支持去年收购LogFire的仓库管理系统(WMS)。 ▲ Oracle将在最新版本的Oracle供应链管理(SCM)Cloud产品…

i5老是显示无服务器,为什么懂电脑的人选择买i5处理器,而不是i7,背后的真实原因?...

摘要&#xff1a;我们在选购电脑的时候经常会被五花八门的型号参数看的神魂颠倒&#xff0c;有很多朋友对cpu的理解也仅限于i7一定比i5好&#xff0c;i5一定比i3好的阶段。然而&#xff0c;对于很多懂电脑的人来说&#xff0c;选购电脑时&#xff0c;都不会买i7的CPU处理器&…

python 实现装饰器设计模式

python 装饰器简单、基本的实现并不复杂。装饰器&#xff08;Decorators&#xff09;模式类似于继承&#xff0c;当你需要为某一个对象添加额外的动作、行为时&#xff0c;在不改变类的情况下可以使用装饰器。这篇文就当做一篇水文&#xff0c;本来不想写&#xff0c;因为这个专…

Excel抽奖小程序

今天分享一个用Excel制作的抽奖小程序。 如上图&#xff0c;制作一个抽奖小界面&#xff0c;滚动显示区域写入“INDIRECT("A"&RANDBETWEEN(2,13))”&#xff0c;按F9键不放&#xff0c;程序开始运行&#xff0c;松开F9键&#xff0c;抽奖完成。 函数解说&#x…