返回类型为IEnumerable<U>却无法使用yield?技术疑问求解
问题分析与解答
你的问题核心在于迭代器块的返回类型必须是指定的接口,而不是接口的实现类。
虽然泛型约束where T : IEnumerable<U>保证了T是IEnumerable<U>的实现,但T本身可能是某个具体类(比如List<U>、HashSet<U>)。而C#的迭代器机制(yield return)只能生成实现了IEnumerable<T>/IEnumerable等接口的匿名迭代器对象,无法直接转换成你指定的T类型——编译器不知道如何把这个匿名迭代器对象转换成你的具体T类(比如没法自动把它变成List)。
你的Eval_B方法没问题,就是因为它直接返回IEnumerable<U>接口类型,完全符合MSDN里规定的迭代器允许的返回类型范围。
要修复Eval_A的错误,有两种可行思路:
- 直接将返回类型改为
IEnumerable<U>,和Eval_B保持一致,这是最简单通用的方案:public IEnumerable<U> Eval_A(T items) { foreach (var item in items) if (item.Equals(id)) yield return item; } - 如果业务上必须返回T类型,那不能用迭代器块,得手动把过滤后的元素收集到T的实例中(这需要T具备可实例化的条件,且支持元素添加):
class Filter<T, U> where T : IEnumerable<U>, ICollection<U>, new() where U : IEquatable<U> { private readonly U id; public Filter(U id) => this.id = id; public T Eval_A(T items) { T result = new T(); foreach (var item in items) if (item.Equals(id)) result.Add(item); return result; } }注意:第二种方案需要额外添加
ICollection<U>和new()的泛型约束,仅适用于支持添加元素的集合类型,通用性远不如第一种。
内容的提问来源于stack exchange,提问作者D G
相关产品推荐
相关产品推荐

