如何编写满足T1可转换为T2约束的泛型Find扩展方法?
实现按类型筛选并应用谓词的泛型Find方法
现有代码与问题
原调用代码:
m_Grabbed = ((IGetGrabbedSMB)a_From.Find(x => x is IGetGrabbedSMB)).GetGrabbed();
初步实现的泛型方法(存在问题):
public static T1 Find<T1, T2>( this List<T2> a_This, Predicate<T1> a_Match ) where T2 : class where T1 : class { return (T1)a_This.Find(x => x is T1 && a_Match( (T1)x ) ); }
该实现无法正常编译,因为泛型约束未明确T1与T2的转换关系,编译器无法保证T2类型的元素可以安全转换为T1。
可行实现方案
方案1:基于OfType<T>的通用扩展方法
利用LINQ的OfType<T1>方法自动筛选可转换为T1类型的元素,再结合FirstOrDefault应用谓词,既安全又简洁:
using System.Linq; // 适用于任意 IEnumerable<object> 集合的版本 public static T1 FindOfType<T1>(this IEnumerable<object> source, Predicate<T1> match) where T1 : class { return source.OfType<T1>().FirstOrDefault(item => match(item)); } // 重载:无需谓词时直接查找第一个匹配类型的元素 public static T1 FindOfType<T1>(this IEnumerable<object> source) where T1 : class { return source.OfType<T1>().FirstOrDefault(); }
方案2:支持任意泛型集合的版本
如果需要支持任意IEnumerable<T>(而非仅IEnumerable<object>),可以扩展为:
using System.Linq; public static T1 FindOfType<T, T1>(this IEnumerable<T> source, Predicate<T1> match) where T1 : class { return source.OfType<T1>().FirstOrDefault(item => match(item)); } public static T1 FindOfType<T, T1>(this IEnumerable<T> source) where T1 : class { return source.OfType<T1>().FirstOrDefault(); }
使用示例
原调用代码可简化为:
// 无需谓词时 m_Grabbed = a_From.FindOfType<IGetGrabbedSMB>().GetGrabbed(); // 需要额外谓词筛选时 m_Grabbed = a_From.FindOfType<IGetGrabbedSMB>(x => x.IsActive).GetGrabbed();
方案优势
- 避免了不安全的强制类型转换,
OfType<T1>会自动过滤掉无法转换的元素 - 方法更通用,支持所有实现
IEnumerable接口的集合(而非仅List<T>) - 代码简洁,复用LINQ的成熟实现,减少自定义逻辑的出错概率
内容的提问来源于stack exchange,提问作者Ylisar
相关产品推荐
相关产品推荐

