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题题解 ...
随机推荐
- C#的扩展方法学习
一,什么是扩展方法? 1,扩展方法使你能够向现有类型“添加”方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型. 2,扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用 ...
- [Java 教程 03] 我的第一个Java程序
现在,大家应该都已经安装好jdk环境了吧!是不是已经跃跃欲试,按耐不住心中的小激动了?那我们现在就来写我们java学习生涯中的第一个java程序. 文件相关设置 为了方便后面大家的学习呢?有一点大家还 ...
- change all column to char
http://bluefrog-oracle.blogspot.com/2011/09/script-submitted-to-otn-to-altter.html Script to Alter v ...
- erlang应用程序启动
(1)erlang应用程序启动过程中,还可以分阶段启动. 在erlang应用程序的资源文件*.app可以定义分步骤启动. *.app中的start_phase字 ...
- tarjan强连通缩点
int dfn[maxn],low[maxn],belong[maxn]; bool instk[maxn]; stack<int>stk; void tarjan(int u){ dfn ...
- 编译自己的jdk(使用openJDK源码编译jdk )
找到openjdk网站(http://hg.openjdk.java.net/) 选择需要编译的版本,浏览readme文件,有获取源码及编译步骤 CentOS-7-x86_64-DVD-1804.is ...
- java SSLContext
1. 什么是SSLSocket JDK文档指出,SSLSocket扩展Socket并提供使用SSL或TLS协议的安全套接字. 这种套接字是正常的流套接字,但是它们在基础网络传输协议(如TCP)上添加了 ...
- Echarts mc地图
Echarts mc地图 echarts官网实例: https://gallery.echartsjs.com/editor.html?c=xSNlA5O-zl 效果: 代码: <html> ...
- CDN技术之--全局负载均衡(GSLB)
负载均衡就是智能调度全局负载均衡(GSLB)的负载均衡主要是在多个节点之间进行均衡,其结果可能直接终结负载均衡过程,也可能将用户访问交付下一层次的(区域或本地)负载均衡系统进行处理.GSLB最通用的是 ...
- 探索Redis设计与实现8:连接底层与表面的数据结构robj
本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...