C# - приведение параметра "объекта" в тип этого объекта?
C#
Всем привет,
Я передаю объект в метод.
Я хочу привести этот объект к определенному классу, чтобы я мог выполнять свои собственные конкретные методы? Как я могу это сделать?
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();
}
}
7 ответов
Ну, вы можете использовать is
ключевое слово как это:
if(objectToMove is Cat)
{
...
}
else if(objectToMove is Pigeon)
{
...
}
Правильный способ сделать это будет:
public interface ICanMove
{
void Move();
}
реализовано как Cat, так и Pigeon:
public class Cat : ICanMove
{
public void Move() { /* do something */ }
}
public class Pigeon : ICanMove
{
public void Move() { /* do something */ }
}
А потом назовите это так:
public void Move(ICanMove objectThatMoves)
{
objectThatMoves.Move();
}
Вы получаете несколько вещей:
- Вы можете только позвонить
Move(ICanMove objectThatMoves)
для объекта, который реализует интерфейс. Если вы попытаетесь передать другой объект, ваша программа не скомпилируется. - Вы теряете условное утверждение. Если вы решили добавить
Dog
который реализуетICanMove
В вашей программе метод Move будет отлично работать без каких-либо изменений. В вашей версии вам придется изменить метод.
Представьте, сколько бы у вас было работы, если бы у вас было is
заявления по всей вашей программе?
Другое решение вместо использования интерфейса состояло бы в том, чтобы иметь базовый класс и переопределить метод Move() в каждом производном классе.
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
}
}
Я думаю, что использование базового класса лучше, если у вас есть свойства или методы, которые являются общими для всех ваших "животных". Таким образом, вам не нужно дублировать код в каждом классе, который реализует интерфейс "IAnimal", описанный выше.
Конечно, если нет общих элементов, интерфейс работает нормально.
Одна небольшая точка... Правильнее не использовать как и вместе, так как подразумеваемая проверка второго типа является избыточной. Либо используйте как следующим образом:
Cat catObject = objectToMove as Cat;
if(catObject!=null)
catObject.Walk();
else
{
Pigeon pigeonObject = objectToMove as Pigeon;
if(pigeonObject!=null)
pigeonObject.Fly();
}
Или сделайте прямой актерский состав, так как вы уверены, что это удастся; это более эффективно и понятно:
if(objectToMove is Cat)
{
Cat catObject = (Cat)objectToMove;
catObject.Walk();
}
else if(objectToMove is Pigeon)
{
Pigeon pigeonObject = (Pigeon)objectToMove;
pigeonObject.Fly();
}
Используя прямое приведение, вы получаете исключение, если оно терпит неудачу, а не нуль. Люди, читающие код, узнают без контекста: "Мы не просто пытаемся понять, можно ли его лечить as
что-то, мы уверены, что мы убедились, что это должно быть возможно.
Вы можете использовать оператор "is", чтобы проверить, является ли объект реализацией определенного класса.
if (objectToMove is Cat)
Просто немного изменений в вашем, и это хорошо, чтобы идти.
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();
}
}
Что бы я сделал, это:
interface IAnimal
{
void Move();
}
Интерфейс
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());
}