【问题标题】:How can I use GetType to access methods/properties of derived classes in C#?如何使用 GetType 访问 C# 中派生类的方法/属性?
【发布时间】:2011-06-03 13:38:07
【问题描述】:

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

狗的属性是犬舍,鸟的属性是巢。

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

if (MyAnimal.GetType = Dog)
{MyKennelMethod(MyAnimal.Kennel)}
else if (MyAnimal.GetType = Bird)
{MyNestMethod(MyAnimal.Nest)}

我猜这行不通。当您只有基类时,有没有办法访问派生类的属性?如果可能的话,我宁愿不要用单独的抽象方法来混淆 Dog 和 Bird 类,因为我更喜欢一个单独的静态类来处理所有方法。我还希望它易于扩展,这样我就可以拥有数百种来自 Animal 的新“动物”。

对于代码语法上的任何错误,我很抱歉,目前我手头没有编辑器。

【问题讨论】:

  • 基于类型层次结构中的类型的流控制通常是一个非常糟糕的主意。
  • 您是否考虑过使用访问者模式?
  • 顺便说一句,该语言称为“C#”,而不是“C Sharp”。
  • @John:等等,它不叫 C 磅!?
  • @John @Brian:我还以为是 C-HashMark!

标签: c# class inheritance abstract


【解决方案1】:

当然,没问题。

Dog dog = myAnimal as Dog;
Bird bird = myAnimal as Bird;
if (dog != null)
   KennelMethod(dog.Kennel);
else if (bird != null)
   NestMethod(bird.Nest);

但是,我建议首先避免这种情况。如果您有一个采用 Animal 的方法,但确实需要 Dog 或 Bird,那么听起来您确实需要 两个方法,一个采用 Dog,一个采用 Bird。

如果可能的话,我宁愿不要用单独的抽象方法来混淆 Dog 和 Bird 类。我还希望它易于扩展,这样我就可以拥有数百种来自 Animal 的新“动物”。

您的要求有些矛盾;您不想在类型代码本身中对类型层次结构的信息进行编码,因此这些内容必须在类型层次结构之外,因此存在可伸缩性问题。

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

【讨论】:

  • 感谢大家的帮助。我现在就去看看访问者模式..
【解决方案2】:

你总是可以施放动物物体。但我不建议以这种方式实现它,请阅读下文。

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";
}

【讨论】:

    【解决方案3】:

    你必须投射:

    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,然后有一个采用 Bird 的重载。

    【讨论】:

      【解决方案4】:

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

      interface SweetHome
      { 
          // members
      }
      
      class Dog: Animal
      {
          public SweetHome Kennel { get; set; }
      }
      
      class Bird: Animal
      {
          public SweetHome Nest { get; set; }
      }
      

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-03-16
        • 2010-09-21
        • 1970-01-01
        • 1970-01-01
        • 2015-10-14
        • 2022-11-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多