La risposta di seguito è stata scritta anni fa e aggiornata nel tempo. A partire da C # 7, è possibile utilizzare la corrispondenza dei motivi:
if (animal is Dog dog)
{
// Use dog here
}
Si noti che dogè ancora nell'ambito dopo l' ifistruzione, ma non è definitivamente assegnato.
No, non c'è. È più idiomatico scrivere questo però:
Dog dog = animal as Dog;
if (dog != null)
{
// Use dog
}
Dato che "come seguito da if" è quasi sempre usato in questo modo, potrebbe avere più senso che ci sia un operatore che esegue entrambe le parti in una volta sola. Questo non è attualmente in C # 6, ma può far parte di C # 7, se la proposta di corrispondenza del modello è implementata.
Il problema è che non è possibile dichiarare una variabile nella parte condizione di ifun'istruzione 1 . L'approccio più vicino che mi viene in mente è questo:
// EVIL EVIL EVIL. DO NOT USE.
for (Dog dog = animal as Dog; dog != null; dog = null)
{
...
}
È semplicemente brutto ... (L'ho appena provato e funziona. Ma per favore, per favore, non farlo. Oh, e puoi dichiararlo dogusando varovviamente.)
Ovviamente potresti scrivere un metodo di estensione:
public static void AsIf<T>(this object value, Action<T> action) where T : class
{
T t = value as T;
if (t != null)
{
action(t);
}
}
Quindi chiamalo con:
animal.AsIf<Dog>(dog => {
// Use dog in here
});
In alternativa, è possibile combinare i due:
public static void AsIf<T>(this object value, Action<T> action) where T : class
{
// EVIL EVIL EVIL
for (var t = value as T; t != null; t = null)
{
action(t);
}
}
Puoi anche usare un metodo di estensione senza un'espressione lambda in modo più pulito rispetto al ciclo for:
public static IEnumerable<T> AsOrEmpty(this object value)
{
T t = value as T;
if (t != null)
{
yield return t;
}
}
Poi:
foreach (Dog dog in animal.AsOrEmpty<Dog>())
{
// use dog
}
1 È possibile assegnare valori nelle ifistruzioni, anche se raramente lo faccio. Tuttavia, non è lo stesso di dichiarare le variabili. Non è terribilmente insolito per me farlo in un whileattimo durante la lettura di flussi di dati. Per esempio:
string line;
while ((line = reader.ReadLine()) != null)
{
...
}
In questi giorni di solito preferisco utilizzare un wrapper che mi consente di utilizzare, foreach (string line in ...)ma considero quanto sopra un modello piuttosto idiomatico. Di solito non è bello avere effetti collaterali all'interno di una condizione, ma le alternative di solito comportano la duplicazione del codice e quando si conosce questo schema è facile ottenere il risultato giusto.
boolcondizione?