Sua pergunta, como eu a entendo, parece basear-se em uma premissa incorreta. Deixe-me ver se consigo reconstruir o raciocínio:
- O artigo vinculado ao descreve como seqüências geradas automaticamente exibem um comportamento "preguiçoso" e mostra como isso pode levar a um resultado contra-intuitivo.
- Portanto, posso detectar se uma determinada instância do IEnumerable exibirá esse comportamento preguiçoso, verificando se ele é gerado automaticamente.
- Como faço isso?
O problema é que a segunda premissa é falsa. Mesmo se você pudesse detectar se um determinado IEnumerable foi ou não o resultado de uma transformação de bloco de iterador (e sim, existem maneiras de fazer isso), isso não ajudaria porque a suposição está errada. Vamos ilustrar o porquê.
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;
}
}
Tudo bem, temos quatro métodos. S1 e S2 são sequências geradas automaticamente; S3 e S4 são sequências geradas manualmente. Agora suponha que tenhamos:
var items = C.Sn(); // S1, S2, S3, S4
S.Add100(items);
Console.WriteLine(items.First().P);
O resultado para S1 e S4 será 0; toda vez que você enumera a sequência, você obtém uma nova referência a um M criado. O resultado para S2 e S3 será 100; toda vez que você enumera a sequência, você obtém a mesma referência a M da última vez. Se o código de sequência é gerado automaticamente ou não, é ortogonal à questão de saber se os objetos enumerados têm identidade referencial ou não. Essas duas propriedades - geração automática e identidade referencial - na verdade não têm nada a ver uma com a outra. O artigo ao qual você vinculou os confunde um pouco.
A menos que um provedor de sequência esteja documentado como sempre oferecendo objetos com identidade referencial , não é aconselhável supor que ele o faz.
ICollection<T>
seria uma escolha melhor, pois nem todas as coleções sãoList<T>
. Por exemplo, matrizes sãoPoint[]
implementadas,IList<T>
mas não sãoList<T>
.