如何基于变量中存储的类型筛选C#集合中的元素
报错原因
OfType<T> 是泛型方法,尖括号内的泛型参数T要求为编译期可确定的静态类型,你传入的animalType是运行时才能拿到值的Type类型变量,无法直接作为泛型参数使用,因此会报变量被当作类型使用的错误。
方案1:运行时类型检查实现(最推荐,性能最优)
根据你的匹配需求选择对应的实现逻辑:
- 仅匹配完全相等的类型(例如传
typeof(Dog)仅返回类型正好为Dog的元素,Dog的子类不算):
int AnimalsOfType(Type animalType) { // 前置参数校验 if (animalType == null) throw new ArgumentNullException(nameof(animalType)); if (!typeof(Animal).IsAssignableFrom(animalType)) throw new ArgumentException("传入类型必须继承自Animal", nameof(animalType)); return animals.Count(a => a != null && a.GetType() == animalType); }
- 匹配所有派生类型(例如传
typeof(Animal)会返回所有集合元素,传Dog也包含Dog的子类实例):
int AnimalsOfType(Type animalType) { if (animalType == null) throw new ArgumentNullException(nameof(animalType)); if (!typeof(Animal).IsAssignableFrom(animalType)) throw new ArgumentException("传入类型必须继承自Animal", nameof(animalType)); return animals.Count(a => animalType.IsInstanceOfType(a)); }
方案2:泛型方法实现(类型安全最优)
如果调用方在编码阶段就可以确定要查询的类型,直接修改方法为泛型写法最简洁,还能享受编译期类型检查:
int AnimalsOfType<T>() where T : Animal { return animals.OfType<T>().Count(); } // 调用示例 int dogCount = AnimalsOfType<Dog>(); int catCount = AnimalsOfType<Cat>();
方案3:反射调用OfType(仅做参考,性能较差)
如果必须使用OfType方法且只能传入运行时Type参数,可以通过反射构造对应的泛型方法执行:
int AnimalsOfType(Type animalType) { if (animalType == null) throw new ArgumentNullException(nameof(animalType)); if (!typeof(Animal).IsAssignableFrom(animalType)) throw new ArgumentException("传入类型必须继承自Animal", nameof(animalType)); // 构造指定泛型参数的OfType方法 var ofTypeMethod = typeof(Enumerable).GetMethod("OfType")?.MakeGenericMethod(animalType); if (ofTypeMethod == null) return 0; // 执行方法并统计数量 var filteredCollection = ofTypeMethod.Invoke(null, new object[] { animals }) as IEnumerable<Animal>; return filteredCollection?.Count() ?? 0; }
内容的提问来源于stack exchange,提问作者K-RUSHer
相关产品推荐
相关产品推荐

