Le contexte : J'ai un tas de chaînes de caractères que je récupère d'une base de données, et je veux les retourner. Traditionnellement, ce serait quelque chose comme ça :
public List<string> GetStuff(string connectionString)
{
List<string> categoryList = new List<string>();
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
{
string commandText = "GetStuff";
using (SqlCommand sqlCommand = new SqlCommand(commandText, sqlConnection))
{
sqlCommand.CommandType = CommandType.StoredProcedure;
sqlConnection.Open();
SqlDataReader sqlDataReader = sqlCommand.ExecuteReader();
while (sqlDataReader.Read())
{
categoryList.Add(sqlDataReader["myImportantColumn"].ToString());
}
}
}
return categoryList;
}
Mais ensuite, je me dis que le consommateur va vouloir itérer à travers les éléments et ne se soucie pas d'autre chose, et j'aimerais ne pas me limiter à une liste, en soi, donc si je renvoie un IEnumerable, tout est bon/flexible. J'ai donc pensé que je pourrais utiliser une conception de type "yield return" pour gérer cela... quelque chose comme ceci :
public IEnumerable<string> GetStuff(string connectionString)
{
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
{
string commandText = "GetStuff";
using (SqlCommand sqlCommand = new SqlCommand(commandText, sqlConnection))
{
sqlCommand.CommandType = CommandType.StoredProcedure;
sqlConnection.Open();
SqlDataReader sqlDataReader = sqlCommand.ExecuteReader();
while (sqlDataReader.Read())
{
yield return sqlDataReader["myImportantColumn"].ToString();
}
}
}
}
Mais maintenant que je lis un peu plus sur le yield (sur des sites comme celui-ci...msdn ne semblait pas le mentionner), c'est apparemment un évaluateur paresseux, qui conserve l'état du populateur, dans l'attente que quelqu'un demande la valeur suivante, et ne l'exécute que jusqu'à ce qu'il retourne la valeur suivante.
Cela semble correct dans la plupart des cas, mais avec un appel à la base de données, cela semble un peu risqué. À titre d'exemple, si quelqu'un demande un IEnumerable que je remplis à partir d'un appel à la base de données, qu'il en parcourt la moitié et qu'il reste coincé dans une boucle... d'après ce que je vois, ma connexion à la base de données va rester ouverte pour toujours.
On dirait qu'il faut s'attendre à des problèmes dans certains cas si l'itérateur ne se termine pas... Est-ce que j'ai raté quelque chose ?