Su pregunta, según tengo entendido, parece estar basada en una premisa incorrecta. Déjame ver si puedo reconstruir el razonamiento:
- El artículo vinculado describe cómo las secuencias generadas automáticamente exhiben un comportamiento "perezoso" y muestra cómo esto puede conducir a un resultado contrario a la intuición.
- Por lo tanto, puedo detectar si una instancia dada de IEnumerable exhibirá este comportamiento perezoso al verificar si se genera automáticamente.
- ¿Cómo puedo hacer eso?
El problema es que la segunda premisa es falsa. Incluso si pudiera detectar si un IEnumerable dado fue el resultado de una transformación de bloque iterador (y sí, hay formas de hacerlo) no ayudaría porque la suposición es incorrecta. Vamos a ilustrar por qué.
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;
}
}
Muy bien, tenemos cuatro métodos. S1 y S2 son secuencias generadas automáticamente; S3 y S4 son secuencias generadas manualmente. Ahora supongamos que tenemos:
var items = C.Sn(); // S1, S2, S3, S4
S.Add100(items);
Console.WriteLine(items.First().P);
El resultado para S1 y S4 será 0; cada vez que enumera la secuencia, obtiene una nueva referencia a una M creada. El resultado para S2 y S3 será 100; cada vez que enumera la secuencia, obtiene la misma referencia a M que obtuvo la última vez. Si el código de secuencia se genera automáticamente o no es ortogonal a la pregunta de si los objetos enumerados tienen identidad referencial o no. Esas dos propiedades, la generación automática y la identidad referencial, en realidad no tienen nada que ver entre sí. El artículo que vinculaste los combina de alguna manera.
A menos que un proveedor de secuencias esté documentado como siempre ofreciendo objetos que tienen identidad referencial , no es prudente suponer que lo hace.
ICollection<T>
sería una mejor opción ya que no todas las colecciones lo sonList<T>
. Por ejemplo, las matrices sePoint[]
implementanIList<T>
pero no lo sonList<T>
.