title author date CreateTime categories
C# Span 入门
lindexi
2018-12-02 11:32:46 +0800
2018-06-18 11:15:43 +0800
C#

本文简单告诉大家如何使用 Span 新的功能
需要知道 Span 是 7.2 才有的功能,如果在正式项目使用,建议安装 Nuget 的方式

在对内存指定的一段的处理,原来的 C# 是比较弱的,因为没有了 C++ 的指针,特别是对于字符串的分割,需要创建多几个字符串。

垃圾微软为了提高 C# 的性能,于是提供了新的类型 Span,这个类可以拿出任意数组的一段,作为一个新的 Span 列表。这样的底层就是指针,而且指针是有判断是否超过范围比 C++ 安全。

首先安装 Nuget System.Memory 库,要求 dotnet framework 4.5 以上,在 UWP 16299 以上,在 dotnet core 2.0 以上

先来写一个简单的程序,创建一个数组,然后使用 Span 指定数组的某一段

            var array = new byte[10];
Span<byte> bytes = array;
bytes = bytes.Slice(start: 2, length: 5); bytes[0] = 5;
Console.WriteLine(array[2]);
Console.WriteLine(bytes[0]);

可以看到对 bytes[0] 的修改就是对 array[2] 的修改,这样可以做到数组重新计算。

也就是对某个计算,需要加上数组的移动,如二维数组的图片计算,例如行是 w 列是 h ,那么计算第 n 行的元素,在以前的时候,就需要在每个的前面加上 w*n,现在可以使用 spanList.Slice(start:w*n, Length:w) 这样重新拿到的数组就是一行,不需要在每个计算都需要添加很多代码

            var array = new byte[10];
Span<byte> bytes = array;
bytes = bytes.Slice(start: 2, length: 5); bytes[0] = 5;
Console.WriteLine(array[2]);
Console.WriteLine(bytes[0]); try
{
bytes[5] = 2;
}
catch (IndexOutOfRangeException e)
{
Console.WriteLine(e);
}

有了这个类就不需要担心写出超过范围代码

stackalloc

如果要和 stackalloc 需要打开不安全代码

然后点击生成高级,选择 C# 7.2 以上

现在可以写出这样的代码

        private static unsafe void DroosorHotir()
{
Span<byte> bytes = stackalloc byte[2];
bytes[0] = 2;
bytes[1] = 3; Console.WriteLine(bytes[0]);
Console.WriteLine(bytes[1]);
}

调用这个函数可以输出 2 和 3 ,使用 stackalloc 可以比申请数组使用更少的资源。因为默认申请的数组都在堆中,不使用需要 gc 才可以回收。但是 stackalloc 可以在变量所在函数结束之后直接就回收,不需要移动内存。

但是 stackalloc 容易出现堆栈溢出,请执行下面的代码,堆栈溢出是 catch 也无法让他不让程序直接退出

            Span<double> bytes = stackalloc double[200000];

即使使用 catch ,软件也会直接退出

            try
{
Span<double> bytes = stackalloc double[200000];
}
catch (Exception)
{
// 接不住
}

AllocHGlobal

除了使用 stackalloc 之外,还可以使用 Marshal.AllocHGlobal 申请一段内存

            IntPtr ptr = Marshal.AllocHGlobal(2);
try
{
var bytes = new Span<byte>((byte*) ptr, 2) {[0] = 42}; Console.WriteLine(bytes[0]);
Console.WriteLine(Marshal.ReadByte(ptr));
}
finally
{
Marshal.FreeHGlobal(ptr);
}

需要注意,申请的内存都需要自己释放

而且需要注意,不要使用比自己申请的内存大的数组

            IntPtr ptr = Marshal.AllocHGlobal(2);
var bytes = new Span<byte>((byte*) ptr, 1000) {[0] = 42};

上面代码申请了内存为 2 但是下一句使用了1000长度

                for (int i = 0; i < 1000; i++)
{
bytes[i] = 25;
Console.WriteLine(bytes[i]);
}

这时虽然很多次都可以赋值成功,但是运行到某个时候,软件就直接退出。

参考:

C# - All About Span: Exploring a New .NET Mainstay

通俗易懂,C#如何安全、高效地玩转任何种类的内存之Span(一)

2018-12-2-C#-Span-入门的更多相关文章

  1. 2018.12.02 Socket编程之初识Socket

    Socket编程主要分为TCP/UDP/SCTP三种,每一种都有各自的优点,所以会根据实际情况决定选用何种Socket,今天开始我将会逐步学习Socket编程,并将学习过程记录于此. 今天学习的是TC ...

  2. OPPO Developers Conference(2018.12.26)

    时间:2018.12.26地点:北京国家会议中心

  3. Tencent Cloud Developers Conference(2018.12.15)

    时间:2018.12.15地点:北京朝阳悠唐皇冠假日酒店

  4. 2018.12.1 Test

    目录 2018.12.1 Test A 串string(思路) B 变量variable(最小割ISAP) C 取石子stone(思路 博弈) 考试代码 B C 2018.12.1 Test 题目为2 ...

  5. 「版本升级」MyEclipse CI 2018.12.0正式发布

    新版本MyEclipse为WildFly 14新增一个新的服务器连接器,改进性能并新增一些Java 10修复程序.新版本为IDE做了几个核心修复,这是MyEclipse 2018一个更棒的升级. [M ...

  6. 微信小程序 - 接口更新记录以及解决方案(2018/12/26)

    2018/8/17 - 背景音频需要在app.json添加requireBackGroundModes 2018/9/12 - 微信更改获取用户信息接口/获取位置等接口 - button 2018/1 ...

  7. 调试大叔V2.1.0(2018.12.17)|http/s接口调试、数据分析程序员辅助开发神器

    2018.12.17 - 调试大叔 V2.1.0*升级http通讯协议版本,完美解决Set-Cookie引起的系列问题:*新增Content-Type编码格式参数,支持保存(解决模拟不同网站或手机请求 ...

  8. C# Span 入门

    原文:C# Span 入门 版权声明:博客已迁移到 http://lindexi.gitee.io 欢迎访问.如果当前博客图片看不到,请到 http://lindexi.gitee.io 访问博客.本 ...

  9. loli的测试-2018.12.9

    模拟赛-2018.12.9 这是NOIP之后第一次模拟赛...但是考的比较悲惨. 非常喜欢写考试总结,不知道为什么... T1:https://www.luogu.org/problemnew/sho ...

  10. 2018.12.7 浪在ACM 集训队第八次测试赛

    2018.12.7 浪在ACM 集训队第八次测试赛  https://blog.csdn.net/QLU_minoz/article/details/84886717   感谢苗学林同学C题和D题题解 ...

随机推荐

  1. eclipse导入了jar查看不了源码解决方法

    当导入源码的时候ctrl+左键的时候,还是查看不了源码.问题一直困扰我很久,百度了很多方法.现在分享下解决的方法. 经过简单整理,如下: 第一步:下载JAD . jad官方地址的官方下载地址是: ht ...

  2. 力扣——candy (分糖果) python实现

    题目描述: 中文: 老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分. 你需要按照以下要求,帮助老师给这些孩子分发糖果: 每个孩子至少分配到 1 个糖果. ...

  3. 启动ABP项目

    1.在官网下载ABP项目 2.打开项目选择解决方案,右击还原NuGet包 3.修改appsettings.json中的ConnectionStrings 例子"ConnectionStrin ...

  4. maven eclipse远程部署tomcat

    pom.xml tomcat 配置信息  <properties><project.build.sourceEncoding>utf8</project.build.so ...

  5. 文本处理工具——sed进阶

    一sed的搜索替代 (一)常见的和替代相关的选项 搜索替代,和vim的写法很像 s///:查找替换,支持使用其它分隔符,s@@@,s### p: 显示替换成功的行,就是打印. w /PATH/TO/S ...

  6. 使用Ueditor点击上传图片时显示延迟的问题

    最近在做一个项目,需要用到Ueditor,但是在点击上传图片的时候,总是隔了4-5秒才显示文件框 查了一些资料,最后发现,只需在 修改:(1) dialog/images/image.js 把imag ...

  7. RCC初始化学习

    一.设置RCC时钟 //#define SYSCLK_HSE #define SYSCLK_FREQ_20MHz //#define SYSCLK_FREQ_36MHz //#define SYSCL ...

  8. STM32串口USART通信总结

    一.GPIO设置USART的初始化 /**************************实现函数******************************************** *函数原型: ...

  9. springboot bootstrap.yml 和 application.yml

    bootstrap.yml可以理解成系统级别的一些参数配置,这些参数一般是不会变动的 application.yml 可以用来定义应用级别的,如果搭配spring-cloud-config使用 app ...

  10. iiview Select 选择框打勾选中的内容label和展示的不一致

    Select选择框里加入了OptionGroup.option ; 以及input输入框支持模糊搜索: 不一致的原因:缺少  :label-in-value="true";官方文档 ...