如果在强类型类上使用IEnumerator,则需要多次访问服务器
本文关键字:服务器 访问 IEnumerator 强类型 如果 | 更新日期: 2023-09-27 18:04:01
这是一个非常简单(而且毫无意义)的var类型具有枚举器属性的例子。这段代码的重点是使用实现IEnumerator
接口的强类型类对集合进行实验。
public class num { public int value { get; set; } }
class Program {
private int[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
static void Main(string[] args) {
Program p = new Program();
var numbers = selectNumbers(p.data);
foreach(num x in numbers) {
Console.WriteLine("Found {0}", x.value.ToString());
}
Console.WriteLine("press [enter] to exit");
Console.Read();
}
static IEnumerable<num> selectNumbers(int[] x) {
//in production app the following would use a reader to get data from database
for(int i = 0; i < x.Length; i++) {
yield return new num { value = x[i] };
Console.WriteLine("Found {0}", x[i].ToString()); // <<<(1)
}
}
}
返回到控制台的结果有点奇怪。结果似乎表明,每次执行foreach
循环的迭代时,行(1)也会执行。
这是否意味着,如果我实现这个结构的数据库设置应用程序,其中selectNumbers
涉及与我们的数据库取得联系,那么每次IEnumerator被使用时,它会使连接?例如,每次它在强类型的num
上使用foreach
循环时,它会与我们的数据库联系吗?
这就是yield return
的工作原理。编译器构造一个状态机来实现IEnumerable<T>
接口。我向您展示的数据库访问示例在this post
中。在本例中,状态机将继续它在上一次迭代中离开的位置,即在while
循环中,而不是在方法的开头:
static IEnumerable<MyModel> SelectTop100Models()
{
var connectionString = ConfigurationManager.ConnectionStrings["XXX"].ConnectionString;
using (var conn = new SqlConnection(connectionString))
using (var cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = "SELECT top 100 * FROM x";
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
// EXECUTION WILL CONTINUE FROM HERE AND NOT AT THE BEGINNING
// OF THE METHOD
yield return new MyModel
{
Id = reader.GetInt32(reader.GetOrdinal("ID")),
Name = reader.GetString(reader.GetOrdinal("Name")),
};
}
}
}
}
因此,您完全不应该担心与数据库建立多个连接。