Por que o compilador C # permite que isso compile e lança uma exceção de tempo de execução quando executado?
class Program
{
static void Main(string[] args)
{
IEnumerable<Test> list = new List<Test>() { new Test() };
foreach(IDisposable item in list)
{
}
}
}
public class Test
{
}
Isso compila com qualquer interface e não compila se você substituir IDisposable por classe concreta.
c#
covariance
ekalchev
fonte
fonte
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.foreach (IDisposable item in list.OfType<IDisposable>())
, mas eu acho que não é o pontoRespostas:
O
foreach
loop tem um elenco implícito. É mais ou menos assim: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 aTest
não pode ser umstring
- mas aTest
pode ser umIDisposable
, porque poderia se referir a uma instância de uma subclasse dessesTest
implementosIDisposable
. Se você tornar aTest
classe selada, ela também falhará na compilaçãoIDisposable
, porque umaTest
instância não poderá ser implementadaIDisposable
.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.fonte