0

I ended up having strange requirement. I have multiple derived classes from one base class, like below.

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.
}

Now at some point of my code, I get base class object (this is argument for a function). Can this function extract exact derived class object from which this base class object was created?

It may not make sense, but I have a strong feeling that there must be a way.

Scherling
  • 1,350
  • 2
  • 13
  • 23
rplusg
  • 3,418
  • 6
  • 34
  • 49
  • every one of those classes could be casted to base, so you would need to make a variable with which you will differenciate them – Milos Romanic Sep 25 '19 at 14:12
  • 4
    `if (bObj is derived1 d1) { /* call derived1 methods on d1 */ } else if (bObj is derived2 d2) { /* call derived2 methods on d2 */ }` – 15ee8f99-57ff-4f92-890c-b56153 Sep 25 '19 at 14:13
  • 2
    Can we get a little more detail here? Possible you don't even need to do that. Maybe you do. Hard to tell from that example. – Fildor Sep 25 '19 at 14:14
  • 2
    In very many cases, you would simply give `base` a *virtual method*, and then have each derived class *override* that virtual method to do its own thing. Then `someFunction(base bObj) { bObj.MyVirtualMethod(); }`. Then you don't need to worry about the exact type bObj is pointing at. The object *itself* knows: If the object is secretly a `derived1`, `derived1.MyVirtualMethod()` will be called. If it's secreately `derived2`, then `derived2.MyVirtualMethod()` will be called. – 15ee8f99-57ff-4f92-890c-b56153 Sep 25 '19 at 14:15
  • @EdPlunkett No there isnt any virtual method, legacy code, do not want to make too many changes. but i like this approach if (bObj is derived1 d1) Let me quickly test, brb in 10 mins. – rplusg Sep 25 '19 at 14:16
  • or you can gather hierarchy information using reflection https://stackoverflow.com/questions/1823655/given-a-c-sharp-type-get-its-base-classes-and-implemented-interfaces – Anton Semenov Sep 25 '19 at 14:18
  • 3
    @rplusg That's a C#7 idiom. If you're stuck in an older version of the language you'll have to do something a little clunkier with "if (a is b) { (a as b).Blah(); }". If you're in C# 8, you can use a pattern matching switch statement. In C#9 you'll be able to write the whole thing in a mashup of common lisp and Ook. In c#10, you'll be farming alien lizard eggs in a dystopian landscape haunted by fear. – 15ee8f99-57ff-4f92-890c-b56153 Sep 25 '19 at 14:22
  • 1
    i think c#10 will come into handy for next raid to area 51. – rplusg Sep 25 '19 at 14:28
  • Correction: Pattern matching was introduced in C#7.0. – 15ee8f99-57ff-4f92-890c-b56153 Sep 25 '19 at 14:39
  • 1
    _"do not want to make too many changes"_ - That sounds like the good ol' "Don't touch it! Ray wrote that. It's completely unreadable and we have to roll backwards around it - but it works." - It's a timebomb. – Fildor Sep 25 '19 at 14:45
  • 1
    Fildor has an appealing point, but there are cases where fixing horrible but stable and well-isolated legacy code can be a lot more expensive than it's worth. – 15ee8f99-57ff-4f92-890c-b56153 Sep 25 '19 at 14:58

3 Answers3

3

C# is a statically typed language.

That means, the type of the objects must be known at compile time.

Having this:

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

you are in trouble.

There are two ways. Either you use pattern matching:

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

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

Advantages: statically typed, type-safe.
Disadvantages: violation of the Open-Closed principle of SOLID.

Or you go dynamic and use double dispatch:

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

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

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

Advantages: ???
Disadvantages: slow, not type safe, can throw at runtime.

dymanoid
  • 14,771
  • 4
  • 36
  • 64
2

f you want to check whether an instance is of an exact type then:

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;
}
0
void someFunction(base bObj)
{
    if (bObj is derived1)
    {

    }
    else if(bObj is derived2)
    {

    }
    ...
}
Mostafa Mahmoud
  • 182
  • 1
  • 10