The answer below was written years ago and updated over time. As of C# 7, you can use pattern matching:
if (animal is Dog dog)
{
// Use dog here
}
Note that dog
is still in scope after the if
statement, but isn't definitely assigned.
No, there isn't. It's more idiomatic to write this though:
Dog dog = animal as Dog;
if (dog != null)
{
// Use dog
}
Given that "as followed by if" is almost always used this way, it might make more sense for there to be an operator which performs both parts in one go. This isn't currently in C# 6, but may be part of C# 7, if the pattern matching proposal is implemented.
The problem is that you can't declare a variable in the condition part of an if
statement1. The closest approach I can think of is this:
// EVIL EVIL EVIL. DO NOT USE.
for (Dog dog = animal as Dog; dog != null; dog = null)
{
...
}
That's just nasty... (I've just tried it, and it does work. But please, please don't do this. Oh, and you can declare dog
using var
of course.)
Of course you could write an extension method:
public static void AsIf<T>(this object value, Action<T> action) where T : class
{
T t = value as T;
if (t != null)
{
action(t);
}
}
Then call it with:
animal.AsIf<Dog>(dog => {
// Use dog in here
});
Alternatively, you could combine the two:
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);
}
}
You can also use an extension method without a lambda expression in a cleaner way than the for loop:
public static IEnumerable<T> AsOrEmpty(this object value)
{
T t = value as T;
if (t != null)
{
yield return t;
}
}
Then:
foreach (Dog dog in animal.AsOrEmpty<Dog>())
{
// use dog
}
1 You can assign values in if
statements, although I rarely do so. That's not the same as declaring variables though. It's not terribly unusual for me to do it in a while
though when reading streams of data. For example:
string line;
while ((line = reader.ReadLine()) != null)
{
...
}
These days I normally prefer to use a wrapper which lets me use foreach (string line in ...)
but I view the above as a pretty idiomatic pattern. It's usually not nice to have side-effects within a condition, but the alternatives usually involve code duplication, and when you know this pattern it's easy to get right.