C# 是否强制“非托管”类型是“blittable”? 非托管类型约束文档Blittable 类型文档是否每个 unmanaged 类型都是“Blittable”?为什么我对此感到担忧“blittable”的定义一个类型是否“blittable”取决于对应代码的细节总结

问题描述

我想知道 C# 7.3's Unmanaged type constraint 是否提供语言支持来强制类型是 blittable。根据 Blittable and Non-Blittable types 正确进行平台调用需要断言返回类型是 blittable:

从平台调用返回的结构必须是 blittable 类型。平台调用不支持非 blittable 结构作为返回类型。

然而,官方文档似乎没有说明 C# 强制 unmanaged 类型是“blittable”的任何地方。我对这样假设感到担忧,因为有证据表明,至少在某一时刻,一种类型是否“blittable”只能凭经验来确定。

非托管类型约束文档

The C# 7.3 "Unmanaged type constraint" proposal 包括以下内容:

非托管约束功能将强制执行 C# 语言规范中称为“非托管类型”的类型类。 ...

...

Blittable 与非托管

F# 语言有一个非常相似的特性,它使用关键字 unmanaged。 blittable 名称来自 Midori 中的使用。可能希望在此处查看优先级并改用非托管。

解决语言决定使用非托管

...

这里的短语“非托管类型”似乎指的是 Unsafe code - Pointer Types of the draft C# 6 specification 中定义的“unmanaged_type”(我在 the C# 5 ECMA standard 中没有找到类似的引用)。 unmanaged_type 定义如下:

非托管类型是任何类型,它不是 reference_type 或构造类型,并且不包含任何嵌套级别的 reference_type 或构造类型字段。换句话说,unmanaged_type 是以下之一:

  • sbytebyteshortushortintuintlongulongcharfloatdoubledecimalbool
  • 任何enum_type
  • 任何pointer_type
  • 任何用户定义的 struct_type 不是构造类型并且仅包含 unmanaged_types 字段。

我还没有发现interop marshaling documentation中提到的C# 7.3的unmanaged类型约束;该文档似乎早于该功能。

Blittable 类型文档

Blittable and Non-blittable Types 声明以下内容是可 blittable 的:

  • System.ByteSystem.SByteSystem.Int16System.UInt16System.Int32System.UInt32System.Int64System.UInt64System.IntPtrSystem.UIntPtrSystem.SingleSystem.Double
  • blittable 类型的一维数组,例如整数数组。但是,包含 blittable 类型的可变数组的类型本身不是 blittable。
  • 仅包含 blittable 类型的格式化值类型(如果它们被封送为格式化类型,则还包含类)。有关格式化值类型的详细信息,请参阅值类型的默认封送处理。

是否每个 unmanaged 类型都是“Blittable”?

起初我认为上面的定义意味着每个 unmanaged 类型都是“blittable”的。但我还没有找到任何直接出现并说明这一点的官方文件。在实现 unmanaged 类型约束功能之前,我发现的最接近的是 this reply(据我了解时间线):

这与互操作封送处理中的 Blittable 类型有什么关系?相同?或相似但略有不同?

是一样的。

这似乎是肯定的证据,但它也是作为设计决策基础的相当薄弱的证据。 (FWIW,这种交换也可以解释为所有“blittable”类型都是 unmanaged,这似乎不太可能是真的。)

然后,根据文档,bool 不是“blittable”,System.Booleanunmanaged。那种复杂性is acknowledged but not directly addressed for the interop marshaler in the original proposal.

为什么我对此感到担忧

我不是一个活跃的 C# 开发人员,而这的历史似乎已经展开,而且肯定有我错过的线索。在我发现的线索中,很多都是否定的。似乎有一段时间 P/Invoke 的实现抵制了区分 blittable 和非 blittable 类型的总内涵定义。换句话说,至少在某些 C# 版本中,先验确认互操作封送拆收器是否认为一个类型是 blittable 是非常重要的(或者可能不可能)。或者至少看起来是这样。例如,Hans Passant wrote in 2015

没有简单的方法可以确定一个类型是否是 blittable,除了它不能正常工作或使用调试器和比较指针值。

另一个线索是 The fastest way to check if a type is blittable?(2012 年提出的问题)中的每个答案的方法似乎都是经验性的。这似乎是进一步否定的证据。

我想可能是所有 unmanaged 类型都是“blittable”,但并非所有“blittable”类型都是 unmanaged。但这只是我的猜测。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)