C#泛型扩展方法类型推断:如何省略冗余的源类型泛型参数
解决方案
C# 泛型方法的类型推断规则要求要么所有泛型参数都能由编译器自动推导,要么必须全部显式指定,不支持部分指定,因此你原来的双泛型参数ConvertTo<T1,T2>方法无法只指定目标类型而省略源类型参数。
最优实现方案:拆分两步调用,用中间值类型承载源类型信息
该方案无需编写大量重复重载,且无额外性能开销:
using System.Runtime.InteropServices; // 只读值类型中间包装,无堆分配开销 public readonly struct ArrayConverter<TSource> { private readonly TSource[] _sourceArray; public ArrayConverter(TSource[] sourceArray) => _sourceArray = sourceArray; public TTarget[] To<TTarget>() { int sourceByteCount = _sourceArray.Length * Marshal.SizeOf<TSource>(); int targetElementByteCount = Marshal.SizeOf<TTarget>(); if (sourceByteCount % targetElementByteCount != 0) { throw new ArgumentException($"数组字节长度必须为 {targetElementByteCount} 的倍数,当前长度为 {sourceByteCount} 字节", nameof(_sourceArray)); } TTarget[] result = new TTarget[sourceByteCount / targetElementByteCount]; Buffer.BlockCopy(_sourceArray, 0, result, 0, sourceByteCount); return result; } } // 仅需一个通用扩展方法,源类型由编译器自动推断 public static ArrayConverter<TSource> Convert<TSource>(this TSource[] buffer) { return new ArrayConverter<TSource>(buffer); }
调用示例
调用时仅需指定目标类型,完全消除冗余参数:
var b = new ushort[] { 1, 256 }; var us = b.Convert().To<byte>(); // 仅需指定目标类型byte,源类型ushort由编译器自动推断 // 验证结果和原实现完全一致 Assert.That(us[0], Is.EqualTo(1)); Assert.That(us[1], Is.EqualTo(0)); Assert.That(us[2], Is.EqualTo(0)); Assert.That(us[3], Is.EqualTo(1));
可选优化
如果你的项目基于.NET 5+运行,可以将Marshal.SizeOf<T>()替换为System.Runtime.CompilerServices.Unsafe.SizeOf<T>(),后者为编译期计算的常量,性能更高,且无需处理值类型装箱问题。
内容的提问来源于stack exchange,提问作者downforme
相关产品推荐
相关产品推荐

