jyo*_*ung 14 c# c#-7.2 system.memory
我注意到,即使未初始化局部变量,以下内容也将编译并执行.这是Span的一个特色吗?
void Uninitialized()
{
Span<char> s1;
var l1 = s1.Length;
Span<char> s2;
UninitializedOut(out s2);
var l2 = s2.Length;
}
void UninitializedOut(out Span<char> s)
{}
Run Code Online (Sandbox Code Playgroud)
Mar*_*ell 18
这看起来像是由引用程序集引起的问题,因为Span<T>具有特定于框架的内部构件的方式.
这意味着在引用程序集中:没有字段(编辑:这不完全正确 - 请参阅脚注).
struct如果分配了所有字段,则认为A 被分配(出于"明确赋值"的目的),并且在这种情况下,编译器看到"已经分配了零字段的全部零:所有好的 - 分配了该变量".但编译器似乎并不知道实际的字段,因此它被误导为允许在技术上无效的东西.
你绝对不应该依赖这种行为!虽然在大多数情况下.locals init应该意味着你实际上并没有太可怕.然而,是目前正在进行的一些工作,让人们抑制 .locals init在某些情况下-我不敢想会发生什么,这情景在这里-尤其是因为Span<T>作品很像ref T-这可以得到非常非常危险的,如果现场真的是不初始化为零.
有趣的是,它可能已经修复:请参阅sharplab上的这个示例.或者,也许sharplab使用的是具体的目标框架,而不是参考组件.
编辑:非常奇怪,如果我将参考组件加载到ildasm反射器中,我可以看到:
.field private initonly object _dummy
Run Code Online (Sandbox Code Playgroud)
这是参考组件中的欺骗字段,旨在阻止这种情况发生,但......现在看起来它不能非常可靠地工作!
更新:显然这里的差异是一个微妙但已知的编译器问题,仍然是出于兼容性原因; 结构的明确赋值考虑本地已知类型的私有字段,但不考虑外部程序集中类型的私有引用类型字段.
Jar*_*Par 15
马克有一个很好的答案.我想详细说明一下历史/背景.
首先,这绝对是一个编译器错误.根据明确赋值的规则,本地未明确分配,任何使用都应该是错误.不幸的是,由于多种原因,这个bug很难解决:
这些合在一起意味着修复这可能会破坏大量现有代码.尽管如此,C#团队还是试图修复C#6.0中的bug,因为它的bug要小得多.但尝试使用此修复程序编译Visual Studio源时,表明围绕客户依赖此错误的担忧是有根据的:有许多构建中断.足以让我们相信它会对大量代码产生负面影响.因此解决方案已撤消.
这里的第二个问题是所有编译器团队成员都不知道这个错误(至少在今天之前).距离修复工作已经3年了,从那时起就有了一些转变.验证我们如何生成参考组件的团队成员Span<T>没有发现此错误,并根据语言规范推荐了当前的设计.我是那些开发者之一:(
仍在讨论这个问题,但我们很可能会更新Span<T>和其他类型的引用程序集策略,以避免这个编译器错误.
感谢您报告此事.抱歉造成的混乱:(