使用 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 的约束与抽象类的主要内容,如果未能解决你的问题,请参考以下文章
PHP中的抽象类与抽象方法/静态属性和静态方法/PHP中的单利模式(单态模式)/串行化与反串行化(序列化与反序列化)/约束类型/魔术方法小结