使用 SafeHandle 的约束与抽象类

Posted

技术标签:

【中文标题】使用 SafeHandle 的约束与抽象类【英文标题】:Constraints vs abstract class using SafeHandle 【发布时间】:2015-09-24 00:36:43 【问题描述】:

BCryptNative 中有一个名为GetInt32Property 的方法。 它具有以下签名:

internal static int GetInt32Property<T>(T algorithm, string property) where T : SafeHandle

此方法仅在 T 类型为 SafeBCryptAlgorithmHandle 或 SafeBCryptHashHandle 时有效。它调用使用这些类型的句柄显式定义的本地方法:

[DllImport("bcrypt.dll", EntryPoint = "BCryptGetProperty", CharSet = CharSet.Unicode)]
internal static extern ErrorCode BCryptGetAlgorithmProperty(SafeBCryptAlgorithmHandle hObject,
                                                            string pszProperty,
                                                            [MarshalAs(UnmanagedType.LPArray), In, Out] byte[] pbOutput,
                                                            int cbOutput,
                                                            [In, Out] ref int pcbResult,
                                                            int flags);

[DllImport("bcrypt.dll", EntryPoint = "BCryptGetProperty", CharSet = CharSet.Unicode)]
internal static extern ErrorCode BCryptGetHashProperty(SafeBCryptHashHandle hObject,
                                                       string pszProperty,
                                                       [MarshalAs(UnmanagedType.LPArray), In, Out] byte[] pbOutput,
                                                       int cbOutput,
                                                       [In, Out] ref int pcbResult,
                                                       int flags);

Microsoft 使用函数指针/委托来指向正确的本机函数。我的问题是,为什么微软不直接使用以下签名实现 GetInt32Property 方法:

internal static int GetInt32Property(SafeHandle algorithm, string property)

使用以下原生方法:

[DllImport("bcrypt.dll", CharSet = CharSet.Unicode)]
internal static extern ErrorCode BCryptGetProperty(SafeHandle hObject,
                                                   string pszProperty,
                                                   [MarshalAs(UnmanagedType.LPArray), In, Out] byte[] pbOutput,
                                                   int cbOutput,
                                                   [In, Out] ref int pcbResult,
                                                   int flags);

这样做有什么缺点吗? (假设传递给 GetInt32Property 的 SafeHandle 始终是 SafeBCryptAlgorithmHandle 或 SafeBCryptHashHandle)。

我只是想知道为什么微软实现这个相对复杂。

是否与:

安全透明代码? 类型安全? (这样您就永远不会使用这两种类型之外的任何其他类型) 是否允许明确使用 SafeHandle?

根据documentation,该类必须被继承,但是当给定SafeHandle 抽象类时,P/Invoked 函数是否正确处理它?它是否适当地增加和减少引用计数?

【问题讨论】:

【参考方案1】:

很难说微软为什么选择以这样或那样的方式实现某些东西,但我可以回答你的观点。

代码并不复杂。用法很明确(类似于GetInt32Property(algorithm, str)。 它不会强制您发送您提到的类型之一,您仍然可以使用不同的类调用它,只要它实现 SafeHandle。 使用的本机方法实际上是相同的。这有点奇怪,但我不是这个特定库的专家,所以这可能是有充分理由的。 像这样的通用方法有一个隐藏的好处。 typeof(T) == typeof(SafeBCryptHashHandle) 类型检查不在运行时完成,而是在 JIT 时间完成。这意味着该方法的执行速度应该比algorith is SafeBCrypthHashHandle 等常规运行时检查稍快。

SafeHandle 类是一个抽象类。这意味着您不能创建它的实例,但可以继承它。本机函数仅获取封送数据,它们没有获取对对象的真实引用。不用担心引用计数。

【讨论】:

啊,太好了!谢谢,JIT 时间段很有趣,虽然我仍然不明白他们为什么为了这么小的(?)好处而增加这样的麻烦。无论如何,谢谢你的回答:)

以上是关于使用 SafeHandle 的约束与抽象类的主要内容,如果未能解决你的问题,请参考以下文章

抽象类与接口

java 抽象类和接口

PHP中的抽象类与抽象方法/静态属性和静态方法/PHP中的单利模式(单态模式)/串行化与反串行化(序列化与反序列化)/约束类型/魔术方法小结

Python之面向对象类的约束与super()深入了解

python 约束与异常处理

抽象类和接口的异同