O foreach
loop tem um elenco implícito. É mais ou menos assim:
using (IEnumerator<Test> iterator = list.GetEnumerator())
{
while (iterator.MoveNext())
{
IDisposable item = (IDisposable) iterator.Current;
// Body of foreach loop here
}
}
Antes dos genéricos, isso era muito mais prático do que ter que converter o código-fonte. Agora não é tão importante, mas seria estranho não compilar. Note que o compilador irá verificar que ele é, pelo menos viável . Se você usar foreach (string item in list)
isso não seria compilado, porque a Test
não pode ser um string
- mas a Test
pode ser um IDisposable
, porque poderia se referir a uma instância de uma subclasse desses Test
implementos IDisposable
. Se você tornar a Test
classe selada, ela também falhará na compilação IDisposable
, porque uma Test
instância não poderá ser implementada IDisposable
.
Basicamente, ele será compilado se uma conversão de Test
para o tipo de iteração for compilada e falhará ao compilar de outra forma. Mas falhará no tempo de execução se uma conversão normal também falhar no tempo de execução.
Test
quais são implementadasIDisposable
. Efetivamente, o foreach tenta converter todos os elementos na interface e lança uma exceção se isso falhar. O mesmo que se você escrevesse(IDisposable)currentElement
. No entanto, não vejo por que não deveria compilar na classe concreta.