我想知道C# 7.3的非托管类型约束是否提供了语言支持来强制一个类型是闪存的。根据斜视和非斜视类型,正确地进行平台调用需要断言返回类型是可闪存的:
从平台调用返回的结构必须是闪存类型。平台调用不支持非闪存结构作为返回类型。
然而,官方文档似乎并没有说明C#强制使用unmanaged类型是“闪电式”。我担心这样的假设,因为有证据表明,至少有一次,某一类型是否“闪电战”只能凭经验来确定。
非托管类型约束文档
C# 7.3“非托管类型约束”建议包括以下内容:
非托管约束特性将为C#语言规范中称为“非托管类型”的类型提供语言执行。..。 ..。 闪存与非托管 F#语言有一个非常类似的特性,它使用非托管关键字。闪电式名称来源于Midori中的用法。可能希望在这里优先使用非托管。 解析语言决定使用非托管的 ..。
这里的短语“非托管类型”似乎是指在不安全代码. C# 6规范草案的指针类型中定义的“不安全代码. C# 6规范草案的指针类型”(我在C# 5 ECMA标准中没有找到类似的引用)。unmanaged_type的定义如下:
unmanaged_type是指不属于reference_type或构造类型的任何类型,并且在嵌套级别上不包含reference_type或构造的类型字段。换句话说,unmanaged_type是以下内容之一:
sbyte、byte、short、ushort、int、uint、long、ulong、char、float、double、decimal或bool。我还没有找到C# 7.3在互操作封送文档中提到的unmanaged类型约束;该文档似乎早于该特性。
闪电式文档
闪电式和非闪电式指出,以下是闪电战:
System.Byte,System.SByte,System.Int16,System.UInt16,System.Int32,System.UInt32,System.Int64,System.UInt64,System.IntPtr,System.UIntPtr,System.Single,System.Double每种unmanaged类型都是“闪电式”吗?
起初,我认为上述定义意味着每个unmanaged类型都是“闪电式”。但我还没有找到任何正式的文件,并说明了这一点。我发现的最接近的是(据我所理解的时间线)在实现unmanaged类型约束特性之前的unmanaged:
这与互操作封送中的Blittable类型有什么关系?同样的?或者相似但有点不同?都是一样的。
这似乎是肯定的证据,但作为设计决策依据的证据也相当薄弱。(FWIW,这种交换也可以解释为所有“闪电式”类型都是unmanaged,这似乎不太可能是真的。)
然后是bool,它不是“闪电战”,System.Boolean是unmanaged,根据文档。并发症在最初的建议中,互操作封送拆收器已被确认,但没有直接解决。
为什么我担心这件事
我不是一个活跃的C#开发人员,而这方面的历史似乎已经展开,而且肯定有我错过的线索。在我发现的线索中,很多都是否定的;似乎有一段时间,P/Invoke的实现抵制了区分闪电式和非闪电式的全面定义。换句话说,至少有一些版本的C#可以预先确认互操作封送拆收器是否认为一种类型是可以闪电式的。或者至少看起来是这样的。例如,汉斯·帕桑特在2015年写道
除了无法正确工作或使用调试器和比较指针值之外,找出类型是否是可闪烁的没有什么容易的方法。
另一条线索是,检查一个类型是否可以闪动的最快方法是什么?中的每一种答案(2012年被问到)似乎都是经验性的。这似乎是负面的进一步证据。
我想可能是所有的unmanaged类型都是“闪存的”,但不是所有的“闪存”类型都是unmanaged。但这只是我的猜测。
发布于 2021-02-01 17:29:31
不,最简单的反例是带bool字段的结构。永远不要闪电战,好满足条件.
这似乎是得出答案是“否”的充分依据。
我认为,汉斯回答的第二部分更有趣:
把这些概念混在一起是没有意义的.
这与我对其他似乎认为unmanaged和“闪电战”是“相同”的观点的解释是相反的。我没有找到任何阐述汉斯的观点,认为把unmanaged和“闪电战”的概念混为一谈是没有意义的。但我已经形成了自己的观点。
“闪电战”的定义
“闪电战”一词似乎对不同的人和不同的环境(例1,2)的含义略有不同。对于这个答案的其余部分,我将使用来自这里的以下定义:
Blittable类型是在托管代码和本机代码中具有相同位级表示的类型.因此,它们不需要转换为另一种格式,以便与本机代码封送.
一个类型是否是“闪电式”取决于对应代码的具体情况。
根据上述定义,类型是否为"blittable“取决于与您交换数据的对应代码是否以与代码相同的方式解释类型的位。bool和BOOL提供了一个很好的例子:
BOOL定义为int,int为32位宽。bool的位从.Net写入文件并读取与bool相同的位不需要转换;任何.Net程序都将以相同的方式解释这种布尔值的位。bool的按位表示与win32 32的BOOL之间的大小差异,这些域之间交换布尔值需要转换。如果不进行转换,发出win32 BOOL的API只能在最重要的24位中设置位来传递真,而.Net很可能将其解释为bool false。摘要
从C#的角度来看,类型是否可以闪动取决于对应代码是否以相同的方式解释表示该类型的位。这将根据对手方的不同而有所不同。在.Net与.Net对手方交换数据的情况下,unmanaged提供了一个约束,保证代表类型的位将被双方正确解释。
对于.Net以外的交易对手来说,目前不存在类似的语言限制。我不认为C#中会存在这样的约束;对手方很多,它们对代表其类型的位的解释肯定是以C#规范无法依赖的方式定义的。
https://stackoverflow.com/questions/65833341
复制相似问题