Considera quanto segue "se il cast":
class A { public void f1() { ... } }
class B : A { public void f2() { ... } }
A a = foo(); // might return A or B
if ( a is B ) {
// Inside block, implicitly "redeclare" a as type B
// It's B, go for it
a.f2();
// Wouldn't compile.
a = new A();
}
Non entriamo nel blocco a meno che a
sia un B
, quindi all'interno del blocco, il compilatore considera a
esattamente come se fosse stato dichiarato come tipo B
. È possibile assegnare null ad esso nel blocco se si tratta di un tipo di riferimento, ma sarebbe un errore in fase di compilazione per assegnare new A()
ad esso, ad esempio (grazie @ThomasEding per aver sollevato tale domanda).
Tutto ciò che potrebbe interrompere quell'ipotesi che a
sia B
, potrebbe altrettanto facilmente interrompere il seguente C # legale:
if ( a is B ) {
B b = a as B;
b.f2();
}
Il primo mi sembra lo zucchero sintattico per quest'ultimo.
Anche se questa funzionalità ha senso, sono sicuro che i ragazzi di Anders Hjelberg hanno caratteristiche più utili da implementare. Mi sto solo chiedendo se è un'idea peggio di quanto io pensi sia.
UPDATE Un'obiezione seria sarebbe che la funzione come descritta aggiunge semantica senza aggiungere sintassi: da una versione della lingua alla successiva, il significato del blocco precedente cambierebbe in modo significativo. Sarebbe più tollerabile con una nuova parola chiave. Ma poi dovresti aggiungere una nuova parola chiave.
Aggiornamento
Una versione più riduttiva di questa funzione è stata implementata in C # 7:
object object2 = new List<Test>();
if (object2 is Dictionary<String, int> foo)
{
Console.WriteLine(foo.Keys);
}