C# - Casting an 'object' parameter into th

2020-07-12 23:58发布

问题:

C#

Hi all,

I pass an object to a method.

I want to cast that object to its specific class so I can perform its own specific methods? How can I do that?

Move( new Cat() );
Move( new Pigeon() );

public void Move(object objectToMove)
{
    if(objectToMove== Cat)
    {
        Cat catObject = objectToMove as Cat;
        catObject.Walk();
    }
    else if(objectToMove== Pigeon)
    {
        Rat pigeonObject = objectToMove as Pigeon;
        pigeonObject.Fly();
    }
}

回答1:

Well, you can use the is keyword like this:

if(objectToMove is Cat)
{
    ...
}
else if(objectToMove is Pigeon)
{
    ...
}


回答2:

The right way to do this would be:

public interface ICanMove
{
   void Move();
}

implemented by both Cat and Pigeon:

public class Cat : ICanMove
{
   public void Move() { /* do something */ }
}

public class Pigeon : ICanMove
{
   public void Move() { /* do something */ }
}

And then call it like this:

public void Move(ICanMove objectThatMoves)
{
   objectThatMoves.Move();
}

You gain several things:

  1. You can only call the Move(ICanMove objectThatMoves) for an object that implements the interface. If you try to pass a different object, your program will not compile.
  2. You lose the conditional statement. If you decide to add a Dog which implements ICanMove to your program, the Move method will work great without any modifications. In your version you will have to change the method.

Imagine how much work you would have if you had is statements all over your program?



回答3:

One small point... It's more correct to not use as and is together as the second type check implied is redundant. Either use as in the following manner:

Cat catObject = objectToMove as Cat;
if(catObject!=null)
    catObject.Walk();
else 
{
    Pigeon pigeonObject = objectToMove as Pigeon;        
    if(pigeonObject!=null)
        pigeonObject.Fly();    
}

Or do a direct cast as you are sure it will succeed; this is both more efficient and more clear:-

if(objectToMove is Cat)    
{        
     Cat catObject = (Cat)objectToMove;        
     catObject.Walk();    
}    
else if(objectToMove is Pigeon)    
{        
     Pigeon pigeonObject = (Pigeon)objectToMove;        
     pigeonObject.Fly();    
}

Using a direct cast you get an exception if it fails, rather than a null. People reading the code will know without context "We're not just trying to see if it can be treated as something, we're sure that we've ascertained that it should be possible.



回答4:

Another solution instead of using an interface would be to have a base class and to override the Move() method in each derived class.

    abstract class Animal
    {
        public abstract void Move();
    }

    public class Cat : Animal
    {
        public override void Move()
        {
            //Cat specific behavior
        }
    }

    public class Bird : Animal
    {
        public override void Move()
        {
            //Bird specific behavior
        }
    }

I think using a base class is better if you have properties or methods that are common to all your "animals". This way you don't have to duplicate code in each class that implements the "IAnimal" interface described above.

Of course if there are no common elements interface works fine.



回答5:

You can use the "is" operator to check if an object is an implementation of a certain class.

if (objectToMove is Cat)


回答6:

Just a bit of change in your and it's good to go.

Move( new Cat() );
Move( new Pigeon() );

public void Move(object objectToMove)
{
    if(objectToMove is Cat)
    {
        Cat catObject = objectToMove as Cat;
        catObject.Walk();
    }
    else if(objectToMove is Pigeon)
    {
        Rat pigeonObject = objectToMove as Pigeon;
        pigeonObject.Fly();
    }
}


回答7:

What I would do is this:

interface IAnimal
{
    void Move();
}

An interface

Then my cat and my bird:

class Cat : IAnimal
{
    public void Move()
    {
        //a cat moves by walking
        this.Walk();
    }

    public void Walk()
    {
        //do logic
    }
}

class Bird : IAnimal
{
    public void Move()
    {
        this.Fly();
    }

    public void Fly()
    {
        //do fly logic
    }
}

So when you're done you get this:

public void Move(IAnimal animal)
{
    animal.Move();
}

And should you want to check the type of your animal you can do this:

public void PrintType(IAnimal animal)
{   
    Console.WriteLine(typeof(animal));
    //or
    Console.WriteLine(animal.GetType());
}