带接口约束的泛型方法能否不装箱返回结构体?
首先要明确两个基础行为:
- 你当前代码中
DoThing里的result.CompareTo(default(T))本身就不会触发装箱:泛型方法针对值类型做JIT编译时,会生成对应值类型的专属方法版本,接口约束下的方法调用会直接绑定到值类型的实现,不需要通过接口引用调度,自然不存在装箱开销。 - 你目前写法中唯一的装箱/拆箱开销发生在
foo方法的返回转换环节:(T)(IComparable)FooBar会先把值类型的FooBar装箱为IComparable接口对象,再拆箱为T类型的值,属于不必要的开销。
优化方案:消除foo方法的装箱拆箱
你可以用System.Runtime.CompilerServices.Unsafe类提供的无开销类型转换来替换原有转换逻辑,修改后的foo方法代码如下:
T foo<T>() where T : IComparable { if (typeof(T) == typeof(MyStruct)) { // 无类型转换开销,不需要装箱/拆箱 return Unsafe.As<MyStruct, T>(ref FooBar); } throw new Exception("Invalid Type Argument"); }
只要你已经提前判断typeof(T) == typeof(MyStruct),这个转换就是完全类型安全的,没有任何运行时开销。如果是面向.NET Framework开发,需要先安装NuGet包System.Runtime.CompilerServices.Unsafe即可使用该方法。
可选适配方案
如果你的业务场景中T只能是实现了IComparable的值类型,可以给泛型约束加上struct限定:
void DoThing<T>() where T : struct, IComparable T foo<T>() where T : struct, IComparable void bar<T>(T value) where T : struct, IComparable
这个约束可以进一步避免引用类型传入带来的潜在装箱逻辑,也能让编译器做更多类型安全校验。
内容的提问来源于stack exchange,提问作者Matthew
相关产品推荐
相关产品推荐

