【问题标题】:C# how to check if base class is instance of derived classC#如何检查基类是否是派生类的实例
【发布时间】:2018-07-05 14:41:08
【问题描述】:

如何从基类中检查它是否是派生类的实例:

class A0 : A {};
class A1 : A {};
class A2 : A {};

class A 
{
    void CheckDerived() 
    {
        if (this is A0) 
        {
            //Do something when instance is A0
        } 
        else if (this is A1) 
        {
            //Do something when instance is A1
        } 
        else if (this is A2) 
        {
            //Do something when instance is A2
        }
    }
}

【问题讨论】:

  • 这是非常糟糕的做法仅供参考,最好有一个所有派生类都覆盖的虚拟方法。
  • 基类永远不应该知道它的派生类。如果没有这样的孩子,你会怎么做?
  • 将方法设为虚拟并覆盖它。任何有类型检查块的地方都是代码异味。
  • 为什么需要这个?你的实际目标是什么?也许有更好的方法来实现这一点。
  • “所以我正在尝试这样的方法来避免对每个派生类进行覆盖” - 为什么?这正是覆盖派上用场的地方!

标签: c# inheritance polymorphism


【解决方案1】:

问题中的代码应该做你想做的事,但是,正如 Danny Goodball 在他的评论中所写,这是一种非常糟糕的做法。

根据open/close principle,声明“软件实体(类、模块、函数等)应该对扩展开放,但对修改关闭”,
为不同孩子处理不同动作的正确方法是使用覆盖:

将方法设为虚拟(作为抽象方法可能会更好),并在每个派生类中用自己的实现覆盖它:

class A
{
     virtual void CheckDerived() { throw new NotImplementedException(); }
}

class A0 : A
{
     override void CheckDerived() { Console.WriteLine("A0"); }
}

class A1 : A
{
     override void CheckDerived() { Console.WriteLine("A1"); }
}

【讨论】:

  • 虽然@mostafa 答案也适用于我需要的东西(我很难解释,因为英语不是我的第一语言),但我选择这个作为正确做法的正确答案。跨度>
  • 我认为覆盖应该在 void 之前,而不是之后?
  • @Lou 感谢您找到我 3 年前的错字:-)
  • 没有问题 :)。我只是注意到,因为我自己尝试过,没有意识到有正确的顺序,Visual Studio 向我抱怨!
【解决方案2】:

你应该使用类类型和 IsAssignableFrom 方法来做到这一点

  public class Program
{
public static void Main()
{
    A a = new A0();
    a.CheckDerived();

 }
}

class A0 : A {};
class A1 : A {};
class A2 : A {};
class A {
public void CheckDerived() {
    if(this.GetType().IsAssignableFrom(typeof(A0))) Console.Write("A0");
    if(this.GetType().IsAssignableFrom(typeof(A1))) Console.Write("A1");
    if(this.GetType().IsAssignableFrom(typeof(A2))) Console.Write("A2");
}
}

【讨论】:

  • 不,你不应该那样做。
  • @HimBromBeere 为什么?
  • 因为你引入了硬依赖。如果孩子多于 A0-2 怎么办?如果我想停用 A1 并将其从代码库中删除怎么办?如果我想添加 A3 怎么办?如果 同事 想要添加 A3 怎么办...此外,您定义了父母内部孩子的行为...我可以继续...打开/关闭...测试。 ..
  • 他只是想知道如何在基类中获取对象的类型,你需要这个的原因有很多,首先例如当想要比较两个对象类型时,或者当你想创建一个动态表达式或想要加载插件时
  • 阅读 cmets ...他正在尝试根据派生类型定义响应。 - 这正是覆盖的用例。
猜你喜欢
  • 2023-03-19
  • 2020-05-20
  • 2021-01-11
  • 2019-03-02
  • 2011-11-05
  • 1970-01-01
  • 2018-10-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多