C#中能否使用Unsafe.As将标记接口安全转换为已知泛型类型?
问题解答
问题1:是否可以安全使用Unsafe.As<IInterface<T1,T2>>()完成转换
- 答案是可以安全使用,前提是你确认缓存的类型约束不会被破坏:
- 你通过
Store方法的泛型参数约束,已经保证了存入缓存的value一定和入参key是同泛型参数的IInterface<T1,T2>实例,类型匹配是100%确定的 - C#中接口类型的引用转换本身不需要修改引用指向的对象数据,普通显式转换唯一多做的操作就是运行时类型校验,确认目标对象确实实现了目标泛型接口
Unsafe.As仅仅是跳过了这个你已经确认不会失败的类型校验,直接返回引用,不会影响后续的接口方法分发逻辑:后续调用接口方法时,CLR依然会根据对象的实际类型的方法表查找执行,不会出现调用错误
- 你通过
- 注意:这种安全是建立在你的缓存逻辑完全符合类型约定的前提下,如果有其他代码绕过
Store方法直接向_cache写入不符合类型要求的对象,Unsafe.As不会抛出转换异常,会直接返回错误类型的引用,后续调用接口方法时会出现不可预期的错误。
问题2:缓存改为Dictionary<object, object>是否会改变结论
- 答案是不会有任何变化:
- 不管你是将实例向上转型为
IInterface还是object存入字典,本质存储的都是同一个对象的引用,对象本身的类型信息没有任何变化 - 只要你能保证取出的对象确实是对应泛型参数的
IInterface<T1,T2>实例,不管是从IInterface还是object类型做Unsafe.As转换,逻辑和安全性完全一致。
- 不管你是将实例向上转型为
额外建议
- 普通显式转换的性能损耗极其微小,只有当这个
Get方法是你的业务热点路径、且性能 profiling 确认类型转换确实是瓶颈时,才建议使用Unsafe.As优化,否则优先保留普通转换的可读性和出错时的快速失败特性。
内容的提问来源于stack exchange,提问作者Bogey
相关产品推荐
相关产品推荐

