Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
148 views
in Technique[技术] by (71.8m points)

c# - Assignment in an if statement

I have a class Animal, and its subclass Dog. I often find myself coding the following lines:

if (animal is Dog)
{
    Dog dog = animal as Dog;    
    dog.Name;    
    ... 
}

For the variable Animal animal;.

Is there some syntax that allows me to write something like:

if (Dog dog = animal as Dog)
{    
    dog.Name;    
    ... 
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...