MSDN文档的错误:关于UnmanagedType.LPStruct和UnmanagedType.Struct

MarshalAsAttribute中,第一个参数类型是UnmanagedType枚举,用以指定对应的非托管数据类型。在这个枚举类型中,有两个非常诡异的值,Unmanaged.LPStructUnmanagedType.Struct。对于这两个枚举值,在MSDN文档中是这么讲的:

Struct

A VARIANT, which is used to marshal managed formatted classes and value types.

LPStruct

A pointer to a C-style structure that you use to marshal managed formatted classes. Valid for platform invoke methods only.

先说StructMarshalAs(UnmanagedType.Struct)实际上并不是指定MarshalVariantMarshalAs(UnmanagedType.Struct)适用于大部分值类型和object类型(不包括其他引用类型),两种情况下,写和不写都没有区别。当用于值类型的情况下,CLR将对应的值类型转换成对应的非托管类型。而当用于object类型时,CLR则是将object转换成VARIANT。文档中指的当是后一种情况,显然不够准确。其实写不写MarshalAs(UnmanagedType.Struct)基本上没有区别,对于可读性也没有任何的帮助,反而由于文档的错误和两种不同的情况增加了复杂性,因此最好建议不要使用这个枚举值。

比较诡异的是 LpStruct ,从字面上理解是传 Struct 的指针。实际上,这个枚举也只能用在两种情况下:

1.     GuidDecimal

这里的作用是告诉CLR多加一层引用。比如Guid对应的非托管类型是GUID,而[MarshalAs(UnmanagedType.LpStruct)] Guid的对应的非托管类型则是Guid*,要多一级指针。这个的作用是可以让你避免使用ref Guid(对应的非托管类型也是GUID*),这样可以让函数原型看起来更加自然一些,特别是GUID*只是用来传入的时候。还有就是在特殊的情况下,可以使用[MarshalAs(UnmanagedType.LpStruct)] ref Guid这样的写法来传递GUID**

2.     一般引用类型,也就是class。和系统关系比较紧密的一些引用类型如StringStringBuilder、数组、委托等除外。

Guid/Decimal不一样的是,这种情况下写和不写没有区别,,因为class本身就是按引用传递,是有一级指针的。如:

class MyClass
  
{
       int b;
   }

对应的非托管的类型为MyClass*

由此可见,文档本身并不没有错,但是基本上对编写者没有任何帮助,说了等于没说。

因为LpStruct这个枚举值并不影响可读性,而且在不同情况下行为不一样(不过可以认为是一致的,只是稍微难以理解),文档本身也没有写清楚用途。由于这些原因,以后很有可能CLR Interop小组会慢慢的停止对LpStruct的支持。我的建议是在程序中尽量不要使用LpStruct。

作者:张羿 (ATField)Blog: http://blog.csdn.net/atfieldEMail: atfield_zhang@hotmail.com 转载请注明出处
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值