如何使用GetType访问C#中派生类的方法/属性?

如何使用GetType访问C#中派生类的方法/属性?,c#,class,inheritance,abstract,C#,Class,Inheritance,Abstract,我有两个派生类,Dog和Bird,它们派生自一个基类Animal 狗有自己的窝,而鸟有自己的窝 我需要一个方法(在一个单独的静态类中),该方法可以接收Animal类的实例,检查类型,然后调用其他方法,将Kennel或Nest作为参数传递给它们,比如: if (MyAnimal.GetType = Dog) {MyKennelMethod(MyAnimal.Kennel)} else if (MyAnimal.GetType = Bird) {MyNestMethod(MyAnimal.Nest)

我有两个派生类,Dog和Bird,它们派生自一个基类Animal

狗有自己的窝,而鸟有自己的窝

我需要一个方法(在一个单独的静态类中),该方法可以接收Animal类的实例,检查类型,然后调用其他方法,将Kennel或Nest作为参数传递给它们,比如:

if (MyAnimal.GetType = Dog)
{MyKennelMethod(MyAnimal.Kennel)}
else if (MyAnimal.GetType = Bird)
{MyNestMethod(MyAnimal.Nest)}
我猜这行不通。当您只有基类时,是否有方法访问派生类的属性?如果可能的话,我不希望用单独的抽象方法将Dog和Bird类弄乱,因为我更喜欢用一个单独的静态类来处理所有的方法。我还希望它可以很容易地伸缩,这样我就可以有数百种不同的新“动物”从动物身上衍生出来


很抱歉,代码语法有任何错误,我手头没有编辑器。

您始终可以投射动物对象。但我不建议以这种方式实现它,请阅读下面的内容

public static void DoSomething(Animal animal)
{
    if (animal is Dog)
    {
      MyKennelMethod((animal as Dog).Kennel);
    }
    else if (animal is Bird)
    {
      MyNestMethod((animal as Bird).Nest);
    }
}
这种方法破坏了继承的目的。正确的方法是公开父对象(动物)中的公共属性。这是一个非常简单的例子。您可以为Home定义一个公共类型,每个子对象以不同的方式公开它:

public abstract class Animal
{
    public abstract string Home;
}

public class Dog : Animal
{
   public override string Home = "Kennel";
}

public class Bird : Animal
{
   public override string Home = "Nest";
}

您始终可以投射动物对象。但我不建议以这种方式实现它,请阅读下面的内容

public static void DoSomething(Animal animal)
{
    if (animal is Dog)
    {
      MyKennelMethod((animal as Dog).Kennel);
    }
    else if (animal is Bird)
    {
      MyNestMethod((animal as Bird).Nest);
    }
}
这种方法破坏了继承的目的。正确的方法是公开父对象(动物)中的公共属性。这是一个非常简单的例子。您可以为Home定义一个公共类型,每个子对象以不同的方式公开它:

public abstract class Animal
{
    public abstract string Home;
}

public class Dog : Animal
{
   public override string Home = "Kennel";
}

public class Bird : Animal
{
   public override string Home = "Nest";
}
你必须投:

void SomeMethod(Animal animal)
{
    var dog = animal as Dog;
    var bird = animal as Bird;

    if (dog != null)
    {
        // it's a dog - do whatever you want with the dog
    }

    if (bird != null)
    {
        // it's a bird - do whatever you want with the bird
    }
}
然而,这是一种代码气味。可能有更好的方法来设计类,所以这种类型的转换是不必要的。例如,
Animal
可能会公开一个
Home
属性,当它是
Dog
时,它会返回一个
Kennel
,当它是
Bird
时,它会返回一个
Nest
。或者,您的静态方法应该只使用一只
,然后使用一只
,您必须施放:

void SomeMethod(Animal animal)
{
    var dog = animal as Dog;
    var bird = animal as Bird;

    if (dog != null)
    {
        // it's a dog - do whatever you want with the dog
    }

    if (bird != null)
    {
        // it's a bird - do whatever you want with the bird
    }
}
然而,这是一种代码气味。可能有更好的方法来设计类,所以这种类型的转换是不必要的。例如,
Animal
可能会公开一个
Home
属性,当它是
Dog
时,它会返回一个
Kennel
,当它是
Bird
时,它会返回一个
Nest
。或者,您的静态方法应该只使用一只
,然后使用一只
,当然,没问题

Dog dog = myAnimal as Dog;
Bird bird = myAnimal as Bird;
if (dog != null)
   KennelMethod(dog.Kennel);
else if (bird != null)
   NestMethod(bird.Nest);
然而,我建议首先避免这种情况。如果你有一个方法,需要一只动物,但真的需要一只狗或一只鸟,那么听起来你真的需要两种方法,一种是需要一只狗,另一种是需要一只鸟

如果可能的话,我不想让Dog和Bird类与单独的抽象方法混在一起。我还希望它可以很容易地伸缩,这样我就可以有数百种不同的新“动物”从动物身上衍生出来

你的要求有些矛盾;您不希望在类型代码本身中编码有关类型层次结构的信息,因此这些内容必须位于类型层次结构之外,因此您存在可伸缩性问题


您是否考虑过使用访客模式?这是对运行时类型的对象执行虚拟分派的一种相当标准的方法,但实际执行的代码存在于类之外。

当然,没有问题

Dog dog = myAnimal as Dog;
Bird bird = myAnimal as Bird;
if (dog != null)
   KennelMethod(dog.Kennel);
else if (bird != null)
   NestMethod(bird.Nest);
然而,我建议首先避免这种情况。如果你有一个方法,需要一只动物,但真的需要一只狗或一只鸟,那么听起来你真的需要两种方法,一种是需要一只狗,另一种是需要一只鸟

如果可能的话,我不想让Dog和Bird类与单独的抽象方法混在一起。我还希望它可以很容易地伸缩,这样我就可以有数百种不同的新“动物”从动物身上衍生出来

你的要求有些矛盾;您不希望在类型代码本身中编码有关类型层次结构的信息,因此这些内容必须位于类型层次结构之外,因此您存在可伸缩性问题


您是否考虑过使用访客模式?这是对对象的运行时类型执行虚拟调度的一种相当标准的方法,但实际执行的代码存在于类之外。

我想Kennel、Nest和将它们作为参数的方法有一些共同点,对吗?如果是,我建议:

interface SweetHome
{ 
    // members
}

class Dog: Animal
{
    public SweetHome Kennel { get; set; }
}

class Bird: Animal
{
    public SweetHome Nest { get; set; }
}

这可以满足你的需要。但我仍然认为,方法应该位于源于动物的类中,而不是位于外部的某个静态类中。

我认为Kennel、Nest和将它们作为参数的方法有一些共同点,对吗?如果是,我建议:

interface SweetHome
{ 
    // members
}

class Dog: Animal
{
    public SweetHome Kennel { get; set; }
}

class Bird: Animal
{
    public SweetHome Nest { get; set; }
}

这可以满足你的需要。但我仍然认为方法应该位于从Animal派生的类中,而不是位于外部的某个静态类中。

基于类型层次结构中的类型的流控制通常是一个非常糟糕的主意。您考虑过使用访问者模式吗?顺便说一句,这种语言叫做“C#”,而不是“C Sharp”。@John:等等,它不是C-Pound@约翰·布莱恩:我还以为是C-HashMark!基于类型层次结构中的类型的流控制通常是一个非常糟糕的主意。您考虑过使用访问者模式吗?顺便说一句,这种语言叫做“C”;,而不是“C Sharp”。@John:等等,它不是C-Pound@约翰·布莱恩:我还以为是C-HashMark!谢谢大家的帮助。我现在就来看看访客模式。谢谢大家的帮助。我现在就来看看访客模式。。