从 IDisposable 实例返回带有 yield 的 IEnumerable<T>
Returning IEnumerable<T> with yield from IDisposable instance
我发现了一个有趣的事情。 C#,.NET 4.0。
我有一个 class 代表 IDisposable 接口。在提到的 class 中,我有一个函数,returns with IEnumerable with 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;
}
}
输出:
"Constructor"
"Getting one"
"Dispose"
"Getting 1"、"Getting 2"在哪里?
如果没有 yield return 和 returning 本地列表,我可以看到这些...
请说明!
这是设计使然的预期行为。当您使用 yield
时,实际发生的是 Get2
方法返回一个由编译器自动实现的类型的实例。该类型实现了 IEnumerable<T>
接口。在枚举可枚举对象之前,迭代器方法中的代码实际上不会被调用。由于您没有枚举 Get2
调用的结果,因此永远不会调用您的代码。要强制执行它,请使用 ToArray()
或 ToList()
:
d.Get2().ToList();
方法 Get2() 中的代码只有在您迭代由该方法编辑的 IEnumerable return 时才会执行。
由于本例中的 IEnumerable 包含两个元素,因此它将输入此代码两次 - 在第一次迭代期间,它将执行第一个两行并在“yield return 1; 处退出函数;
在下一次迭代期间,它将进入函数并在 "Console.WriteLine("Getting 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();
}
我发现了一个有趣的事情。 C#,.NET 4.0。 我有一个 class 代表 IDisposable 接口。在提到的 class 中,我有一个函数,returns with IEnumerable with 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;
}
}
输出: "Constructor" "Getting one" "Dispose"
"Getting 1"、"Getting 2"在哪里? 如果没有 yield return 和 returning 本地列表,我可以看到这些...
请说明!
这是设计使然的预期行为。当您使用 yield
时,实际发生的是 Get2
方法返回一个由编译器自动实现的类型的实例。该类型实现了 IEnumerable<T>
接口。在枚举可枚举对象之前,迭代器方法中的代码实际上不会被调用。由于您没有枚举 Get2
调用的结果,因此永远不会调用您的代码。要强制执行它,请使用 ToArray()
或 ToList()
:
d.Get2().ToList();
方法 Get2() 中的代码只有在您迭代由该方法编辑的 IEnumerable return 时才会执行。 由于本例中的 IEnumerable 包含两个元素,因此它将输入此代码两次 - 在第一次迭代期间,它将执行第一个两行并在“yield return 1; 处退出函数; 在下一次迭代期间,它将进入函数并在 "Console.WriteLine("Getting 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();
}