Si je comprends bien, votre question semble reposer sur une prémisse incorrecte. Voyons si je peux reconstruire le raisonnement:
- L'article lié à décrit comment les séquences générées automatiquement présentent un comportement "paresseux" et montre comment cela peut conduire à un résultat contre-intuitif.
- Par conséquent, je peux détecter si une instance donnée de IEnumerable va présenter ce comportement paresseux en vérifiant si elle est générée automatiquement.
- Comment je fais ça?
Le problème est que la deuxième prémisse est fausse. Même si vous pouviez détecter si un IEnumerable donné était le résultat d'une transformation de bloc d'itérateur (et oui, il existe des moyens de le faire), cela ne serait pas utile car l'hypothèse est fausse. Illustrons pourquoi.
class M { public int P { get; set; } }
class C
{
public static IEnumerable<M> S1()
{
for (int i = 0; i < 3; ++i)
yield return new M { P = i };
}
private static M[] ems = new M[]
{ new M { P = 0 }, new M { P = 1 }, new M { P = 2 } };
public static IEnumerable<M> S2()
{
for (int i = 0; i < 3; ++i)
yield return ems[i];
}
public static IEnumerable<M> S3()
{
return new M[]
{ new M { P = 0 }, new M { P = 1 }, new M { P = 2 } };
}
private class X : IEnumerable<M>
{
public IEnumerator<X> GetEnumerator()
{
return new XEnum();
}
// Omitted: non generic version
private class XEnum : IEnumerator<X>
{
int i = 0;
M current;
public bool MoveNext()
{
current = new M() { P = i; }
i += 1;
return true;
}
public M Current { get { return current; } }
// Omitted: other stuff.
}
}
public static IEnumerable<M> S4()
{
return new X();
}
public static void Add100(IEnumerable<M> items)
{
foreach(M item in items) item.P += 100;
}
}
D'accord, nous avons quatre méthodes. S1 et S2 sont des séquences générées automatiquement; S3 et S4 sont des séquences générées manuellement. Supposons maintenant que nous ayons:
var items = C.Sn(); // S1, S2, S3, S4
S.Add100(items);
Console.WriteLine(items.First().P);
Le résultat pour S1 et S4 sera 0; chaque fois que vous énumérez la séquence, vous obtenez une nouvelle référence à un M créé. Le résultat pour S2 et S3 sera 100; chaque fois que vous énumérez la séquence, vous obtenez la même référence à M que vous avez obtenue la dernière fois. Que le code de séquence soit généré automatiquement ou non est orthogonal à la question de savoir si les objets énumérés ont une identité référentielle ou non. Ces deux propriétés - génération automatique et identité référentielle - n'ont en fait rien à voir l'une avec l'autre. L'article auquel vous avez lié les confond un peu.
À moins qu'un fournisseur de séquence ne soit documenté comme offrant toujours des objets ayant une identité référentielle , il est imprudent de supposer qu'il le fait.
ICollection<T>
serait un meilleur choix car toutes les collections ne le sont pasList<T>
. Par exemple, les tableauxPoint[]
implémententIList<T>
mais ne le sont pasList<T>
.