Poniższa odpowiedź została napisana lata temu i aktualizowana z biegiem czasu. Począwszy od C # 7, możesz używać dopasowywania wzorców:
if (animal is Dog dog)
{
// Use dog here
}
Zauważ, że dog
po if
instrukcji nadal znajduje się w zakresie , ale nie jest ostatecznie przypisany.
Nie, nie ma. Bardziej idiomatyczne jest jednak napisanie tego:
Dog dog = animal as Dog;
if (dog != null)
{
// Use dog
}
Biorąc pod uwagę, że „jak następuje, jeśli” jest prawie zawsze używane w ten sposób, bardziej sensowne może być wprowadzenie operatora, który wykonuje obie części za jednym razem. To nie jest obecnie w C # 6, ale może być częścią C # 7, jeśli propozycja dopasowania wzorca zaimplementowano .
Problem polega na tym, że nie możesz zadeklarować zmiennej w części warunkowej if
instrukcji 1 . Najbliższe podejście, jakie przychodzi mi do głowy, to:
// EVIL EVIL EVIL. DO NOT USE.
for (Dog dog = animal as Dog; dog != null; dog = null)
{
...
}
To po prostu paskudne ... (Właśnie to wypróbowałem i działa. Ale proszę, nie rób tego. Och, i możesz zadeklarować dog
użycievar
oczywiście .)
Oczywiście możesz napisać metodę rozszerzającą:
public static void AsIf<T>(this object value, Action<T> action) where T : class
{
T t = value as T;
if (t != null)
{
action(t);
}
}
Następnie zadzwoń za pomocą:
animal.AsIf<Dog>(dog => {
// Use dog in here
});
Alternatywnie możesz połączyć te dwa elementy:
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);
}
}
Możesz także użyć metody rozszerzenia bez wyrażenia lambda w bardziej przejrzysty sposób niż pętla for:
public static IEnumerable<T> AsOrEmpty(this object value)
{
T t = value as T;
if (t != null)
{
yield return t;
}
}
Następnie:
foreach (Dog dog in animal.AsOrEmpty<Dog>())
{
// use dog
}
1 Możesz przypisywać wartości w if
instrukcjach, chociaż rzadko to robię. To nie to samo, co deklarowanie zmiennych. To nie jest strasznie nietypowe dla mnie zrobić w while
chociaż kiedy czyta strumienie danych. Na przykład:
string line;
while ((line = reader.ReadLine()) != null)
{
...
}
W dzisiejszych czasach zwykle wolę używać opakowania, które pozwala mi używać, foreach (string line in ...)
ale postrzegam powyższe jako dość idiomatyczny wzór. To zwykle nie miło mieć skutki uboczne w obrębie stanu, ale alternatywy obejmują zazwyczaj powielania kodu, a gdy wiesz, ten wzór jest to łatwe, aby uzyskać prawo.
bool
warunek?