.NET Native UWP应用中Span<T>及相关类型无法正常工作
解决.NET Native UWP应用中Span及相关类型的异常问题
我看到你在.NET Native编译的UWP应用里碰到了Span<T>、ReadOnlySpan<T>这类类型没法正常工作的问题,尤其是递归使用Slice方法的场景。结合你给出的复现步骤,我来帮你梳理问题原因和可行的解决方案:
完整问题复现步骤(补充你未写完的代码逻辑)
- 打开安装了最新更新的Visual Studio 2017
- 创建目标版本为10240的UWP项目(实际所有UWP版本都存在该问题,这个版本不是必须的)
- 从NuGet安装System.Memory包(得勾选「包含预发行版」,因为早期正式版对.NET Native的支持不够完善)
- 在
MainPage.cs里添加如下完整代码:
private void MainPage_Loaded(object sender, RoutedEventArgs e) { void Recursive(ReadOnlySpan<char> param) { if (param.Length == 0) return; tx1.Text += Environment.NewLine; tx1.Text += new string(param.ToArray()); // 递归调用Slice截取从索引1开始的子Span Recursive(param.Slice(1)); } // 触发测试 Recursive("Hello World".AsSpan()); }
- 切换到Release模式(因为.NET Native只在Release编译时启用),编译运行应用,会发现应用崩溃或者输出结果不符合预期。
问题根源
这是因为早期的.NET Native编译器对Span<T>这类值类型的递归处理存在缺陷——当Span<T>作为递归方法的参数时,编译器的优化逻辑会破坏Span<T>的内部结构,进而导致内存访问异常或者数据错误。另外,早期版本的System.Memory包对.NET Native的适配也没做到位。
可行解决方案
方案1:升级开发环境和NuGet包
这是最彻底的解决办法:
- 把Visual Studio 2017升级到15.9及以上版本(微软在后续更新里修复了.NET Native对
Span<T>的编译问题) - 将
System.Memory包升级到2.0.0及以上的正式版(不用再用预发行版了,正式版已经完善了对.NET Native的支持)
方案2:调整代码逻辑,避免递归传递Span
如果暂时没法升级环境,可以换个写法,不在递归方法里直接传Span<T>:
private void MainPage_Loaded(object sender, RoutedEventArgs e) { string input = "Hello World"; void Recursive(int startIndex) { if (startIndex >= input.Length) return; // 在递归方法内部根据索引生成Span ReadOnlySpan<char> param = input.AsSpan(startIndex); tx1.Text += Environment.NewLine; tx1.Text += new string(param.ToArray()); Recursive(startIndex + 1); } Recursive(0); }
通过传递起始索引而非直接传递Span<T>,绕开.NET Native编译器的缺陷。
方案3:禁用.NET Native对Span的特定优化
在项目的Default.rd.xml文件里添加下面的配置,告诉.NET Native编译器不要优化Span<T>相关类型:
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata"> <Application> <Assembly Name="System.Memory" Dynamic="Required All"/> <Type Name="System.Span`1" Dynamic="Required All"/> <Type Name="System.ReadOnlySpan`1" Dynamic="Required All"/> </Application> </Directives>
这个配置能强制.NET Native保留Span<T>的完整类型信息,避免优化导致的异常。
验证方式
修改完成后切换到Release模式编译运行,看看应用是不是能正常输出递归截取的字符串,而且没有崩溃或者异常情况。
内容的提问来源于stack exchange,提问作者Fernando
相关产品推荐
相关产品推荐

