如何动态获取可分配给IEnumerable<T>的类型以规避三元判断?
解决方案
以下是可落地的实现方案,按推荐优先级排序:
方案1:泛型扩展方法(优先推荐)
性能最优,无额外运行时开销,支持编译期类型校验,适合编译时可确定集合为泛型IEnumerable<>的场景:
public static class EnumerableExtensions { public static IEnumerable<SelectItem> ToSelectItems<T>(this IEnumerable<T> source) { if (source == null) throw new ArgumentNullException(nameof(source)); // 匹配Countries类型集合 if (typeof(T) == typeof(Countries)) { return source.Cast<Countries>() .Select(country => new SelectItem { Value = country.Name, Text = country.Name }); } // 默认逻辑:所有其他类型统一调用ToString() return source.Select(item => new SelectItem { Value = item?.ToString(), Text = item?.ToString() }); } }
调用代码直接简化为一行,完全不需要三元判断:
var selectItems = parentList.ToSelectItems();
方案2:dynamic动态调度(代码最简)
如果编译期无法确定parentList的类型(比如parentList声明为object/非泛型IEnumerable),可以用dynamic规避手动类型判断:
var selectItems = ((IEnumerable<dynamic>)parentList).Select(item => { if (item is Countries country) { return new SelectItem { Value = country.Name, Text = country.Name }; } return new SelectItem { Value = item?.ToString(), Text = item?.ToString() }; });
注意:该方案会产生少量运行时开销,且失去编译期类型校验能力,类型不兼容问题会在运行时抛出。
方案3:反射获取泛型参数(灵活性最高)
如果需要主动获取IEnumerable<>绑定的泛型类型做更复杂的逻辑,可以用反射实现类型提取:
首先实现获取泛型元素类型的工具方法:
private static Type GetEnumerableGenericType(Type collectionType) { // 查找集合实现的IEnumerable<>泛型接口 var genericEnumerable = collectionType.GetInterfaces() .FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEnumerable<>)); // 兼容数组类型 if (genericEnumerable == null && collectionType.IsArray) { return collectionType.GetElementType(); } return genericEnumerable?.GetGenericArguments().FirstOrDefault(); }
调用示例:
var elementType = GetEnumerableGenericType(parentList.GetType()); IEnumerable<SelectItem> selectItems; if (elementType == typeof(Countries)) { selectItems = ((IEnumerable<Countries>)parentList) .Select(c => new SelectItem { Value = c.Name, Text = c.Name }); } else { selectItems = ((IEnumerable<string>)parentList) .Select(s => new SelectItem { Value = s, Text = s }); }
内容的提问来源于stack exchange,提问作者Ms1
相关产品推荐
相关产品推荐

