返回IEnumerable< T>与IDisposable实例的yield
本文关键字:IDisposable 实例 yield IEnumerable 返回 | 更新日期: 2023-09-27 18:11:44
我发现了一件有趣的事情。c#。NET 4.0。我有一个代表IDisposable接口的类。在上面提到的类中,我有一个函数,它返回IEnumerable和yield return。在调用时,控件跳过该函数。不要介入。例子:
class Program
{
static void Main(string[] args)
{
using (DispClass d = new DispClass())
{
d.Get2();
d.Get1();
}
}
}
public class DispClass: IDisposable
{
public DispClass()
{
Console.WriteLine("Constructor");
}
public void Dispose()
{
Console.WriteLine("Dispose");
}
public int Get1()
{
Console.WriteLine("Getting one");
return 1;
}
public IEnumerable<int> Get2()
{
Console.WriteLine("Getting 1");
yield return 1;
Console.WriteLine("Getting 2");
yield return 2;
}
}
输出:"构造函数"一"处理"
"得到1","得到2"在哪里?没有yield return,返回一个本地列表,我可以看到这些…
请解释!
这是预期的行为和设计。当您使用yield
时,实际发生的情况是Get2
方法返回由编译器自动实现的类型的实例。该类型实现IEnumerable<T>
接口。在枚举对象被枚举之前,迭代器方法中的代码实际上不会被调用。由于您没有枚举Get2
调用的结果,因此您的代码永远不会被调用。要强制它,使用ToArray()
或ToList()
:
d.Get2().ToList();
方法Get2()中的代码只有在迭代该方法返回的IEnumerable时才会执行。由于本例中的IEnumerable包含两个元素,因此它将两次输入此代码—在第一次迭代中,它将执行前两行并在"yield return 1;在下一次迭代中,它将进入函数并在"Console"行开始执行。WriteLine(" get 2");"并从那里继续。
因此,如果您没有遍历这两个项目,即在获得值1之后,您没有移动到IEnumerable中的下一个项目,那么该函数将不会再次输入。试着把你的程序改成下面的代码,以便更好地理解。
static void Main(string[] args)
{
using (DispClass d = new DispClass())
{
var lst = d.Get2();
//d.Get1();
foreach (var a in lst)
{
break;
}
}
Console.ReadKey();
}