2018-12-2-C#-Span-入门
| 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]);
}
这时虽然很多次都可以赋值成功,但是运行到某个时候,软件就直接退出。
参考:
2018-12-2-C#-Span-入门的更多相关文章
- 2018.12.02 Socket编程之初识Socket
Socket编程主要分为TCP/UDP/SCTP三种,每一种都有各自的优点,所以会根据实际情况决定选用何种Socket,今天开始我将会逐步学习Socket编程,并将学习过程记录于此. 今天学习的是TC ...
- OPPO Developers Conference(2018.12.26)
时间:2018.12.26地点:北京国家会议中心
- Tencent Cloud Developers Conference(2018.12.15)
时间:2018.12.15地点:北京朝阳悠唐皇冠假日酒店
- 2018.12.1 Test
目录 2018.12.1 Test A 串string(思路) B 变量variable(最小割ISAP) C 取石子stone(思路 博弈) 考试代码 B C 2018.12.1 Test 题目为2 ...
- 「版本升级」MyEclipse CI 2018.12.0正式发布
新版本MyEclipse为WildFly 14新增一个新的服务器连接器,改进性能并新增一些Java 10修复程序.新版本为IDE做了几个核心修复,这是MyEclipse 2018一个更棒的升级. [M ...
- 微信小程序 - 接口更新记录以及解决方案(2018/12/26)
2018/8/17 - 背景音频需要在app.json添加requireBackGroundModes 2018/9/12 - 微信更改获取用户信息接口/获取位置等接口 - button 2018/1 ...
- 调试大叔V2.1.0(2018.12.17)|http/s接口调试、数据分析程序员辅助开发神器
2018.12.17 - 调试大叔 V2.1.0*升级http通讯协议版本,完美解决Set-Cookie引起的系列问题:*新增Content-Type编码格式参数,支持保存(解决模拟不同网站或手机请求 ...
- C# Span 入门
原文:C# Span 入门 版权声明:博客已迁移到 http://lindexi.gitee.io 欢迎访问.如果当前博客图片看不到,请到 http://lindexi.gitee.io 访问博客.本 ...
- loli的测试-2018.12.9
模拟赛-2018.12.9 这是NOIP之后第一次模拟赛...但是考的比较悲惨. 非常喜欢写考试总结,不知道为什么... T1:https://www.luogu.org/problemnew/sho ...
- 2018.12.7 浪在ACM 集训队第八次测试赛
2018.12.7 浪在ACM 集训队第八次测试赛 https://blog.csdn.net/QLU_minoz/article/details/84886717 感谢苗学林同学C题和D题题解 ...
随机推荐
- 【问题解决方案】本地仓库删除远程库后添加到已有github仓库时仓库地址找不到的问题(github仓库SSH地址)
参考: 我参考我自己.jpg 背景: 想添加一下远程库,github主页找了半天,Google搜索了半天,都没有找到,所以这里写一个,记录一下 1-格式分析:git@github.com:用户名/仓库 ...
- 在线px转换rem工具
今天推荐一个在线工具,在线px转换rem工具 只要输入1rem = 多少px即可在线转换 和cssrem插件差不多的功能 rem在线转换工具: http://www.ofmonkey.com/fr ...
- 字符串String的使用方法
var ddd = "举头望明月,低头思故乡" document.writeln(ddd.split(''));//选择字符串中的一个标识符,将字符串分割成数组; var slic ...
- html使用字符串拼接js函数时传字符串参数
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...
- 【串线篇】spring泛型依赖注入原理
spring泛型依赖注入原理 不管三七二十一 servlet :加注解@servlet service:加注解@service dao:加注解@Repository 这相当于在容器中注册这些个类
- webpack 学习三 模式
开发环境(development)和生产环境(production)的构建目标差异很大.在开发环境中,我们需要具有强大的.具有实时重新加载(live reloading)或热模块替换(hot modu ...
- 使用jxls导出Excel报表
导入jar包: <dependency> <groupId>net.sf.jxls</groupId> <artifactId>jxls-core< ...
- codeblocks编译调试C语言二级指针小记
夜已深,暂时附上一个截图,后面慢慢道来. 下图时用codeblocks调试C语言的界面,codeblocks版本是17.12nosetup版,也为继承mingw,我用的编程器是tdm-gcc-5.1. ...
- MariaDB 插入查询
在本章中,我们将学习如何在表中插入数据. 将数据插入表需要INSERT命令. 该命令的一般语法是INSERT,后跟表名,字段和值. 查看下面给出的一般语法 - INSERT INTO tablenam ...
- yii2 后台前后台 前后台登陆、退出问题
问题描述:我使用前后台分离 配置如下: 'user' => [ 'identityClass' => 'app\models\User', 'enableAutoLogin' => ...