On m'a récemment fait remarquer que diverses méthodes d'extension Linq (telles que Where
, Select
, etc.) renvoient un IEnumerable<T>
qui se trouve être également IDisposable
. Ce qui suit correspond à True
new int[2] {0,1}.Select(x => x*2) is IDisposable
Dois-je supprimer les résultats d'une expression Where
?
Chaque fois que j'appelle une méthode renvoyant IEnumerable<T>
, est-ce que j'accepte (potentiellement) la responsabilité d'appeler disposer lorsque j'en ai fini?
Non, vous n'avez pas à vous en préoccuper.
Le fait qu'ils retournent une implémentation IDisposable
est un détail d'implémentation - c'est parce que les blocs d'itérateur dans l'implémentation Microsoft du compilateur C # créent un type nique qui implémente les deux IEnumerable<T>
et IEnumerator<T>
. Ce dernier étend IDisposable
, c'est pourquoi vous le voyez.
Exemple de code pour le démontrer:
using System;
using System.Collections.Generic;
public class Test
{
static void Main()
{
IEnumerable<int> foo = Foo();
Console.WriteLine(foo is IDisposable); // Prints True
}
static IEnumerable<int> Foo()
{
yield break;
}
}
Notez que vous faites devez prendre note du fait que IEnumerator<T>
implémente IDisposable
. Donc, chaque fois que vous répétez explicitement, vous devez vous en débarrasser correctement. Par exemple, si vous voulez parcourir quelque chose et être sûr que vous aurez toujours la valeur a, vous pouvez utiliser quelque chose comme:
using (var enumerator = enumerable.GetEnumerator())
{
if (!enumerator.MoveNext())
{
throw // some kind of exception;
}
var value = enumerator.Current;
while (enumerator.MoveNext())
{
// Do something with value and enumerator.Current
}
}
(Une boucle foreach
le fera automatiquement, bien sûr.)