如何声明值为泛型类型的键值对数组?避免使用System.Object
解决泛型Pair数组兼容不同类型实例的问题
这个问题的核心在于:Pair<int>和Pair<string>是完全不同的类型,它们没有直接的共同父类(除了最顶层的object),所以没法直接放到同一个泛型参数固定的数组里。不过我们可以通过定义一个非泛型的基类或接口来解决这个问题——既不用把Value声明为object,又能让不同泛型版本的Pair实例共存于同一个数组。
方案1:使用非泛型抽象基类
先定义一个包含Name属性的抽象基类,同时提供一个抽象的非类型化值属性,让泛型子类去实现:
public abstract class PairBase { public string Name { get; set; } // 这里只是暴露一个非类型化的访问入口,泛型子类的Value仍然是强类型的T public abstract object UntypedValue { get; } } public class Pair<T> : PairBase { public T Value { get; set; } public override object UntypedValue => Value; }
现在你就可以用PairBase[]来声明数组,完美容纳不同类型的Pair实例:
PairBase[] pairs = new PairBase[] { new Pair<int> { Name = "Age", Value = 44 }, new Pair<string> { Name = "FirstName", Value = "Frank" }, };
方案2:使用非泛型接口
如果你更倾向于接口而非抽象类,也可以定义一个非泛型接口,让泛型Pair<T>实现它:
public interface IPair { string Name { get; set; } object UntypedValue { get; } } public class Pair<T> : IPair { public string Name { get; set; } public T Value { get; set; } // 显式实现接口,避免在泛型类的公共API里暴露非类型化的属性 object IPair.UntypedValue => Value; }
对应的数组声明就变成:
IPair[] pairs = new IPair[] { new Pair<int> { Name = "Age", Value = 44 }, new Pair<string> { Name = "FirstName", Value = "Frank" }, };
后续使用强类型Value
如果需要在遍历数组时获取强类型的Value,可以用模式匹配来判断具体类型:
foreach (var pair in pairs) { switch (pair) { case Pair<int> intPair: Console.WriteLine($"Age: {intPair.Value}"); break; case Pair<string> stringPair: Console.WriteLine($"First Name: {stringPair.Value}"); break; } }
这样既满足了数组容纳不同类型实例的需求,又保持了Pair<T>中Value的强类型特性,完全不用把Value直接声明为object。
内容的提问来源于stack exchange,提问作者Frank Rem
相关产品推荐
相关产品推荐

