如何实现每个键对应不同泛型类型的泛型委托字典?
实现类型安全的多类型泛型委托字典
要实现每个键对应不同T类型的Func<T,T>委托集合,同时保持编译时类型安全,可以通过非泛型基类+泛型子类+自定义集合封装的方式实现,完全避免object强制转换或dynamic的问题。
步骤1:定义转换委托的封装类
首先创建一个非泛型抽象基类,作为字典存储的统一类型;再实现泛型子类来封装具体的Func<T,T>委托,同时提供类型安全的调用入口:
public abstract class TypedTransformer { // 非泛型调用入口(内部使用,外部无需直接调用) public abstract object Invoke(object input); } public class Transformer<T> : TypedTransformer { private readonly Func<T, T> _transformFunc; public Transformer(Func<T, T> transformFunc) { _transformFunc = transformFunc ?? throw new ArgumentNullException(nameof(transformFunc)); } // 实现基类的非泛型方法,内部做类型校验 public override object Invoke(object input) { if (!(input is T typedInput)) throw new ArgumentException($"输入必须是{typeof(T).Name}类型", nameof(input)); return _transformFunc(typedInput); } // 外部调用的类型安全方法 public T Invoke(T input) => _transformFunc(input); }
步骤2:自定义类型安全的字典集合
封装一个专用的字典类,提供类型安全的Add和Invoke方法,确保操作时的类型正确性:
public class TransformerDictionary { private readonly Dictionary<string, TypedTransformer> _innerDict = new Dictionary<string, TypedTransformer>(); /// <summary> /// 添加指定类型的转换委托 /// </summary> /// <typeparam name="T">委托的输入输出类型</typeparam> /// <param name="key">关联的字符串键</param> /// <param name="transformFunc">输入输出为T的转换委托</param> public void Add<T>(string key, Func<T, T> transformFunc) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException("键不能为空或空白", nameof(key)); if (transformFunc == null) throw new ArgumentNullException(nameof(transformFunc)); if (_innerDict.ContainsKey(key)) throw new ArgumentException($"键{key}已存在", nameof(key)); _innerDict.Add(key, new Transformer<T>(transformFunc)); } /// <summary> /// 调用指定键的转换委托 /// </summary> /// <typeparam name="T">委托的输入输出类型</typeparam> /// <param name="key">关联的字符串键</param> /// <param name="input">输入参数</param> /// <returns>转换后的结果</returns> public T Invoke<T>(string key, T input) { if (!_innerDict.TryGetValue(key, out var transformer)) throw new KeyNotFoundException($"未找到键{key}"); if (!(transformer is Transformer<T> typedTransformer)) throw new InvalidOperationException($"键{key}对应的委托类型不是{typeof(T).Name}"); return typedTransformer.Invoke(input); } }
步骤3:使用示例
这个集合可以安全地存储不同类型的转换委托,调用时必须指定正确的类型,编译时就能检查类型错误:
var transformerDict = new TransformerDictionary(); // 添加不同类型的转换逻辑 transformerDict.Add<int>("翻倍", x => x * 2); transformerDict.Add<string>("转大写", s => s.ToUpperInvariant()); transformerDict.Add<DateTime>("加一天", dt => dt.AddDays(1)); // 类型安全地调用 int doubled = transformerDict.Invoke<int>("翻倍", 5); // 结果:10 string upperStr = transformerDict.Invoke<string>("转大写", "hello"); // 结果:"HELLO" DateTime tomorrow = transformerDict.Invoke<DateTime>("加一天", DateTime.Today); // 结果:明天的日期
方案优势
- 编译时类型安全:添加和调用都明确指定
T,类型不匹配的错误会在编译阶段暴露,而非运行时。 - 避免繁琐转换:内部自动处理类型校验和转换,外部调用无需手动强制转换
object。 - 比dynamic更可靠:所有类型逻辑都是显式的,不会出现动态类型的意外行为,长期维护更稳定。
内容的提问来源于stack exchange,提问作者Dobby1235
相关产品推荐
相关产品推荐

