C#编译时判断泛型是否为数组类型 实现普通与数组类型分离Set方法
可行实现方案
利用C#泛型方法重载的匹配规则,分别实现普通类型和数组类型的处理分支,不需要运行时类型判断,也无需维护大量if/else分支,实现代码如下:
public class JsonDictionary { // 普通类型Key public static readonly Key<int> Int = new Key<int> { Name = "INT" }; // 数组类型Key,无需额外配置,自动走数组验证逻辑 public static readonly Key<int[]> Int3 = new Key<int[]> { Name = "INT3" }; public static readonly Key<ushort[]> UShort3 = new Key<ushort[]> { Name = "USHORT3" }; public static readonly Key<double[]> Double3 = new Key<double[]> { Name = "DOUBLE3" }; private readonly IDictionary<string, object> _data = new Dictionary<string, object>(); // 普通类型的Set方法 public void Set<T>(Key<T> key, T obj) { // 若Key有自定义验证逻辑则执行 key.Validate?.Invoke(obj); _data[key.Name] = obj; } // 数组类型的Set方法,优先级高于普通泛型方法,所有数组类型会自动匹配此重载 public void Set<TElement>(Key<TElement[]> key, TElement[] obj) { // 通用数组验证:所有3元素数组统一校验长度 if (obj.Length != 3) { throw new FormatException($"Illegal {key.Name}"); } // 若有数组特有的自定义验证也可在此执行 key.Validate?.Invoke(obj); _data[key.Name] = obj; } public T Get<T>(Key<T> key) { return (T)_data[key.Name]; } public class Key<T> { public string Name { get; init; } // 可选的自定义验证委托,支持特殊类型的扩展校验 public Action<T> Validate { get; init; } } }
使用方式和原有逻辑完全兼容,无需修改已有调用代码:
var d = new JsonDictionary(); d.Set(JsonDictionary.Int, 42); var i = d.Get(JsonDictionary.Int); // 所有数组类型自动走长度校验,无需额外编码 d.Set(JsonDictionary.Int3, new int[] { 1, 2, 3 }); var i3 = d.Get(JsonDictionary.Int3); d.Set(JsonDictionary.UShort3, new ushort[] { 1, 2, 3 }); var us3 = d.Get(JsonDictionary.UShort3); d.Set(JsonDictionary.Double3, new double[] { 1.1, 2.2, 3.3 }); var d3 = d.Get(JsonDictionary.Double3); // 长度不匹配的数组依然会抛出异常 Assert.Throws<FormatException>(() => d.Set(JsonDictionary.Int3, new int[] { 1, 2 })); Assert.Throws<FormatException>(() => d.Set(JsonDictionary.UShort3, new ushort[] { 1 }));
方案特点
- 完全通过编译期泛型重载匹配实现逻辑分发,无运行时类型检查开销,无需维护冗长的分支判断
- 后续新增其他数组类型(如
long[]、float[]等)只需新增对应的Key静态字段即可,无需修改Set方法的核心实现 - 保留了扩展能力,若某类特殊类型需要自定义验证逻辑,只需给Key的
Validate属性赋值对应委托即可,无需改动框架代码
内容的提问来源于stack exchange,提问作者malat
相关产品推荐
相关产品推荐

