跨度T不需要局部变量赋值.这是功能吗? [英] Span<T> does not require local variable assignment. Is that a feature?

查看:104
本文介绍了跨度T不需要局部变量赋值.这是功能吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我注意到,即使未初始化局部变量,也将编译并执行以下内容.这是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)
{}

解决方案

这似乎是由引用程序集引起的问题,由于Span<T>具有特定于框架的内部结构的方式,因此必不可少.

这意味着在引用程序集中:没有字段(这不是很正确-参见脚注).

如果已分配所有字段,则将struct视为已分配(出于确定分配"的目的),在这种情况下,编译器将看到所有零个零字段均已分配:全部良好-此变量为分配".但是编译器似乎并不了解 actual 字段,因此被误导为允许使用在技术上无效的内容.

您绝对不应该依赖此行为!尽管在大多数情况下,.locals init意味着您实际上并没有感到太可怕了.但是,目前有 正在进行中,以便在某些情况下允许人们抑制 .locals init-我害怕认为那会发生什么情况-尤其是因为Span<T>的作用类似于ref T-如果 really 字段未初始化为零,则可能会非常危险. >

有趣的是,它可能已经被固定:请参阅这个例子在Sharplab上.另外,sharplab可能正在使用具体的目标框架,而不是参考程序集.


很奇怪,如果我将参考组件加载到ildasm或反射器中,我可以看到:

.field private initonly object _dummy

这是参考程序集中的欺骗字段,该字段是 meant ,可以阻止这种情况的发生,但是...看起来它现在无法正常工作!


更新:显然,这里的区别是细微但已知的编译器问题,出于兼容性原因而保留;结构的确定分配考虑本地已知类型的私有字段,但不考虑外部程序集中类型的私有 reference-type 字段.

I notice that the following will compile and execute even though the local variables are not initialized. Is this a feature of 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)
{}

解决方案

This looks like an issue caused by reference assemblies, required because of the way that Span<T> has framework-specific internals.

This means that in the reference assembly: there are no fields (edit: this isn't quite true - see footnote).

A struct is considered assigned (for the purposes of "definite assignment") if all fields are assigned, and in this case the compiler is seeing "all zero of zero fields have been assigned: all good - this variable is assigned". But the compiler doesn't seem to know about the actual fields, so it is being misled into allowing something that is not technically valid.

You definitely shouldn't rely on this behaving nicely! Although in most cases .locals init should mean you don't actually get anything too horrible. However, there is currently some work in progress to allow people to suppress .locals init in some cases - I dread to think what could happen in that scenario here - especially since Span<T> works much like a ref T - that could get very very dangerous if the field really isn't initialized to zero.

Interestingly, it might already be fixed: see this example on sharplab. Alternatively, maybe sharplab is using a concrete target framework, rather than reference assemblies.


Edit: very oddly, if I load the reference assembly into ildasm or reflector, I can see:

.field private initonly object _dummy

which is the spoofed field in the reference assembly that is meant to stop this from happening, but... it looks like it isn't working very reliably right now!


Update: apparently the difference here is a subtle but known compiler issue that remains for compatibility reasons; definite assignment of structs considers private fields of types that are known locally, but does not consider private reference-type fields of types in external assemblies.

这篇关于跨度T不需要局部变量赋值.这是功能吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆