如何在C#中存储不同泛型类型的Key对象并调用其方法?
C# 存储不同泛型类型Key对象的解决方案
核心思路:引入非泛型基接口
由于Key<T>的不同泛型实例(如Key<int>、Key<string>)属于不同类型,无法直接存入同一强类型数组。通过定义非泛型接口,让所有Key<T>实现该接口,就能统一存储和调用公共成员。
1. 定义非泛型接口IKey
提取所有Key<T>实例需要共享的公共成员到接口中:
public interface IKey { int Count { get; set; } bool[] Orders { get; set; } IComparer Comparer { get; } }
2. 修改Key<T>实现接口
调整原泛型类,实现IKey接口,同时保留泛型特性:
public class Key<T> : IKey where T : IComparable<T> { private T[] _data; public int Count { get; set; } // 将原字段orders改为属性,符合接口规范 public bool[] Orders { get; set; } = { false, false, false }; // 保留泛型Comparer,同时显式实现非泛型接口的Comparer public IComparer<T> Comparer { get; } IComparer IKey.Comparer => Comparer; public Key(T[] data, IComparer<T> comparer) { _data = data; Count = data.Length; Comparer = comparer; } public T this[int index] { get { if (index >= Count || index < 0) throw new IndexOutOfRangeException(); return _data[index]; } } }
3. 统一存储与遍历
现在可以用IKey[]数组存储任意Key<T>实例,安全遍历调用公共成员:
// 初始化不同类型的Key对象 var intKey = new Key<int>(new[] { 1, 2, 3 }, Comparer<int>.Default); var stringKey = new Key<string>(new[] { "a", "b", "c" }, StringComparer.Ordinal); // 存入同一数组 IKey[] keys = { intKey, stringKey }; // 遍历处理公共逻辑 foreach (var key in keys) { Console.WriteLine($"Key元素数量: {key.Count}"); for (int i = 0; i < key.Orders.Length; i++) { Console.WriteLine($"排序位置{i}的状态: {key.Orders[i]}"); } }
4. 处理类型特定逻辑(可选)
如果需要针对特定类型执行操作,用模式匹配安全转换,避免硬编码:
foreach (var key in keys) { if (key is Key<int> intKeyObj) { int firstElement = intKeyObj[0]; Console.WriteLine($"第一个int类型元素: {firstElement}"); } else if (key is Key<string> stringKeyObj) { string firstElement = stringKeyObj[0]; Console.WriteLine($"第一个string类型元素: {firstElement}"); } // 新增类型时,只需添加对应分支,无需修改数组存储逻辑 }
方案优势
- 类型安全:避免
object数组的强制转换风险,减少运行时异常 - 扩展性:新增类型时仅需实现
Key<T>,核心存储和遍历逻辑无需改动 - 代码清晰:通过接口明确公共成员,可读性更强
内容的提问来源于stack exchange,提问作者KasparLee
相关产品推荐
相关产品推荐

