【问题标题】:differentiate between multiple derived class objects, with given base class object使用给定的基类对象区分多个派生类对象
【发布时间】:2019-09-25 23:43:36
【问题描述】:

我最终有一个奇怪的要求。我有来自一个基类的多个派生类,如下所示。

class base
{
}

class derived1 : base
{
}
class derived2 : base
{
}
.
.
.
.
class derivedN : base
{
}

void someFunction(base bObj)
{
//get me derived class object with which bObj was created.
}

现在在我的代码中,我得到了基类对象(这是一个函数的参数)。此函数能否提取出创建此基类对象的确切派生类对象?

这可能没有意义,但我有一种强烈的感觉,一定有办法。

【问题讨论】:

  • if (bObj is derived1 d1) { /* call derived1 methods on d1 */ } else if (bObj is derived2 d2) { /* call derived2 methods on d2 */ }
  • 我们可以在这里获得更多细节吗?可能你甚至不需要这样做。也许你会。从那个例子很难看出。
  • 在很多情况下,您只需给base一个虚拟方法,然后让每个派生类覆盖该虚拟方法它自己的东西。然后someFunction(base bObj) { bObj.MyVirtualMethod(); }。那么你不需要担心 bObj 指向的确切类型。对象本身知道:如果对象是秘密的derived1derived1.MyVirtualMethod()会被调用。如果它是secreately derived2,那么derived2.MyVirtualMethod() 将被调用。
  • @rplusg 这是一个 C#7 习语。如果你被困在旧版本的语言中,你将不得不用“if (a is b) { (a as b).Blah(); }”做一些更笨拙的事情。如果您使用的是 C# 8,则可以使用模式匹配 switch 语句。在 C#9 中,您将能够在 common lisp 和 Ook 的混搭中编写整个内容。在 c#10 中,您将在充满恐惧的反乌托邦景观中养殖外星蜥蜴蛋。
  • 我认为 c#10 会在下一次突袭 51 区时派上用场。

标签: c#


【解决方案1】:

C# 是一种静态类型语言。

这意味着,对象的类型必须在编译时知道

有这个:

void someFunction(Base bObj)
{
    // bObj.Derived1Method() if bObj is Derived1
    // or
    // bObj.Derived2Method() if bObj is Derived2
}

你有麻烦了。

有两种方法。要么你使用模式匹配:

switch (bObj)
{
    case Derived1 d1:
        d1.Derived1Method();
        break;

    case Derived2 d2:
        d2.Derived2Method();
        break;
}

优点:静态类型,类型安全。
缺点:违反了SOLID的开闭原则。

或者你去dynamic并使用双重调度:

void someFunction(Base bObj)
{
    dynamic d = (dynamic)bObj;
    DoSomething(d);
}

void DoSomething(Derived1 d1) => d1.Derived1Method();

void DoSomething(Derived2 d2) => d2.Derived2Method();

优点:???
缺点:速度慢,类型不安全,会在运行时抛出。

【讨论】:

  • 方案3:咬住酸苹果,重构。
【解决方案2】:

如果你想检查一个实例是否是一个确切的类型,那么:

switch (bObj.GetType())
{
      case typeof(derived1):

          Console.WriteLine("bObj is an instance of derived1");
          break;
      case typeof(derived2):
          Console.WriteLine("bObj is an instance of derived2");
          break;
      .....................
      case typeof(derivedn):
          Console.WriteLine("bObj is an instance of derivedn");
          break;
      default:
          Console.WriteLine("bObj is instance of base");
          break;
}

【讨论】:

  • 更好地使用模式匹配。
  • 模式匹配告诉我 oObj 是 DerivedN 的实例还是子类
  • @Fildor,模式匹配也适用于if-else
  • @PeterSteel,OP的问题描述没有多级继承,所以没关系。
  • @dymanoid 是的,没错。以为您是在专门谈论“模式匹配 switch 语句”。我的错。
【解决方案3】:
void someFunction(base bObj)
{
    if (bObj is derived1)
    {

    }
    else if(bObj is derived2)
    {

    }
    ...
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-07
    • 2020-08-06
    • 2013-11-29
    • 2011-07-20
    相关资源
    最近更新 更多