使用yield return返回泛型参数
使用yield return返回泛型参数
希望这不是个重复的问题,在网上找不到相关信息\n我在下面的扩展方法中遇到了一个奇怪的编译时错误:\n错误信息:\n“The body of \'TestBed.EnumerableExtensions.AddRange(TCol, System.Collections.Generic.IEnumerable)\' cannot be an iterator block because \'TCol\' is not an iterator interface type”\n这是否意味着编译器在确定一个方法是否适合使用“yield return”时不考虑泛型约束?\n我在一个使用泛型参数定义集合的类中使用了这个扩展方法。类似这样(还有一些类型转换操作符):\n
public class TestEnumwhere TCol : class, ICollection , new() { TCol _values = default(TCol); public TestEnum(IEnumerable values) { _values = (TCol)(new TCol()).AddRange(values); } public TestEnum(params TItem[] values) : this(values.AsEnumerable()) { } ... }
\n然后这样使用(记住我定义了类型转换操作符):\n
TestEnum, string> col = new List
() { "Hello", "World" }; string someString = col; Console.WriteLine(someString);
\n最初,我的扩展方法是这样的:\n
public static IEnumerableAddRange (this IEnumerable e, IEnumerable values) { ... }
\n这样编译是可以通过的,但结果是:\n“Unhandled Exception: System.InvalidCastException: Unable to cast object of type \'1[System.String]\' to type \'System.Collections.Generic.List
1[System.String]\'. ”\n有没有其他的方法来做到这一点?\n
\n如您所请求,这里有一个小例子:\n
class Program { public static void Main() { TestEnum, string> col = new List
() { "Hello", "World" }; string someString = col; Console.WriteLine(someString); } } public class TestEnum where TCol : class, ICollection , new() { TCol _values = default(TCol); public TestEnum(IEnumerable values) { _values = (TCol)(new TCol()).AddRange(values); } public TestEnum(params TItem[] values) : this(values.AsEnumerable()) { } public static implicit operator TItem(TestEnum item) { return item._values.FirstOrDefault(); } public static implicit operator TestEnum (TCol values) { return new TestEnum (values); } } public static class EnumerableExtensions { public static IEnumerable AddRange (this IEnumerable e, IEnumerable values) { foreach (var cur in e) { yield return cur; } foreach (var cur in values) { yield return cur; } } }
\n为了重现编译时异常:\n
class Program { public static void Main() { TestEnum, string> col = new List
() { "Hello", "World" }; string someString = col; Console.WriteLine(someString); } } public class TestEnum where TCol : class, ICollection , new() { TCol _values = default(TCol); public TestEnum(IEnumerable values) { _values = (TCol)(new TCol()).AddRange(values); } public TestEnum(params TItem[] values) : this(values.AsEnumerable()) { } public static implicit operator TItem(TestEnum item) { return item._values.FirstOrDefault(); } public static implicit operator TestEnum (TCol values) { return new TestEnum (values); } } public static class EnumerableExtensions { public static TCol AddRange (this TCol e, IEnumerable values) where TCol : IEnumerable { foreach (var cur in e) { yield return cur; } foreach (var cur in values) { yield return cur; } } }
(Returning generic parameter with yield return)这个问题的出现主要是由于在上述代码中,方法`AddRange`的返回类型被定义为`void`,而不是`IEnumerable
为了解决这个问题,我们需要将方法的返回类型改为`IEnumerable
public static IEnumerableAddRange (this TCol collection, IEnumerable range) where TCol : ICollection { var list = collection as List ; if (list != null) { list.AddRange(range); return list; } foreach (var item in range) collection.Add(item); return collection; }
通过这样的修改,我们可以在调用`AddRange`方法时,使用`yield return`语句从集合中逐个返回元素。这样,我们就可以在方法外部使用`foreach`循环来遍历返回的元素。
,为了在泛型方法中使用`yield return`语句返回集合中的元素,我们需要将方法的返回类型定义为`IEnumerable
问题的出现原因是方法返回的是一个迭代器块,而不是特定的集合类型。迭代器块只能返回IEnumerable
解决方法是修改方法实现,不再返回集合,而是直接向集合中添加元素。可以使用ICollection
以下是修改后的AddRange()方法的示例代码:
public static void AddRange(this ICollection collection, IEnumerable items) { foreach (var item in items) collection.Add(item); }
第二个尝试的代码片段为什么会导致异常呢?迭代器块只能返回IEnumerable
最后,你的AddRange()方法实现是解决这个问题的方法。非常感谢你的帮助!
文章结束。
返回值为泛型参数的yield return语句为什么会出错以及解决方法
在上述代码中,方法M的返回值类型是T,而T是一个泛型参数,并且要求T必须实现IEnumerable
泛型类型参数T可以是List
关于你的方法,TCol的作用是什么?为什么不直接这样写:
public static IEnumerable
this IEnumerable
{
foreach(TItem item in s1) yield return item;
foreach(TItem item in s2) yield return item;
}
顺便提一下,这个方法已经存在,它被称为"Concat"。
同意。我最初尝试使用IEnumerable.Concat,但在编译时出现了类似的错误,所以我根据Jared Par的版本为添加到IEnumerable实例的方法(我已经在项目中使用了它,所以我只是克隆了这个函数)编写了自己的版本。这导致我尝试使用泛型来抽象类型,希望它能起作用,但没有成功(导致了这个问题)。我希望能找到一个适用于IEnumerable