0

Basically there're 2 classes.

class Motor {
   int a;
   int b;
   int c;
}

class Title : Motor {
    int d;
    int e;
}

Now a function is passed with an instance of Motor class.

bool AssignNums(Motor m)
{
   Title t = (Title)m;   //throws exception
   //Do other things with "t"
}

And it's called from,

void AddNums()
{
   Motor m = new Motor();
   m.a = 23;
   m.b = 78;
   m.c = 109;
   AssignNums(m);
}

The above line where the casting is done, doesn't work. It throws a null pointer exception.

I tried:

bool AssignNums(Motor m)
{
   Title t = new Title();
    t  = (Title)m; // Doesn't work.
   //Do other things with "t"
}

The above approach also doesn't work.

Coming from a C++ background, it's kinda difficult to understand how casting works in C#.

In C++ below code will work.

bool AssignNums(Motor* m)
{
   Title* t = (Title*)m; //Will work
   //Do other things with "t"
}

How can this be done in C#? Without tons of code to implement "reflection" or something like that...

donguy76
  • 610
  • 3
  • 12
  • 33
  • Please edit your question and show an example of code using `AssignNums` – Lee Taylor Sep 05 '19 at 22:00
  • 1
    There are two cast syntaxes in C#. Try the other one: `if (m is Title t) { /* code */ }`. In your code, you know `m` is a `Title` and you have a non-null variable that references it as a `Title` – Flydog57 Sep 05 '19 at 22:02
  • 1
    It sounds like you are passing `null` into `AssignNums` when calling it. As @LeeTaylor suggested, can you edit your question to show how you're calling `AssignNums`? – Scott Mitchell Sep 05 '19 at 22:03
  • Where are you calling `AssignNums`? It looks like you're passing an instance of the `Motor` base class. – Lee Sep 05 '19 at 22:05
  • 1
    @LeeTaylor I have updated the question with how AssignNums is being called. – donguy76 Sep 05 '19 at 22:09
  • 1
    The reason you get an exception is that you are passing a `Motor` to `AssignNums` and then casting it to the sub-class `Title`. The object is not a `Title`, so the cast fails and throws. By the way, in `C++`, you shouldn't be using old-fashioned C-style casts, you should be using `dynamic_cast<>`, `reinterpret_cast<>`, etc. – Flydog57 Sep 05 '19 at 22:12
  • 4
    Your C++ code has undefined behaviour; you are not allowed to cast a pointer to an instance of a base class to a pointer to a derived class unless it really *is* an instance of the derived class! The whole point of C# is that it turns your bad C++ code into sensible behaviour: *crash the program* is sensible behaviour when the rules are broken. – Eric Lippert Sep 05 '19 at 22:12

2 Answers2

6

In C#, you can't cast an object to a more specific subclass. Imagine what could happen if it were possible:

class Foo : Motor
{
    int z;
}

Foo m = new Foo();

bool AssignNums(Motor m)
{
   Title t = (Title)m;   // Pretend it doens't throw an exception
   //Do other things with "t"
   t.d = 42; // Oopps! The actual object is Foo, not Title, so there is no field called d
             // InvalidCastException is thrown at the line that attempts the cast
}

You can convert it at runtime if the actual type is compatible with the desired one:

bool AssignNums(Motor m)
{
   Title t = m as Title;   
   if (t != null)
   {
       // Do stuff with t
   }
}

Beginning with C# 7, you can use the shorter form

bool AssignNums(Motor m)
{
   if (m is Title t)
   {
       // Do stuf with t
   }
}

If handling multiple subclasses, you can also use switch..when

switch (m)
{
    case Title t when m is Title:
        // Do something with t
        break;
    case Foo f when m is Foo:
        // Do something with f
        break;
}

Note, though, if you're branching based on the subclass present at runtime, it's a sign that you may have a design issue.

Eric J.
  • 147,927
  • 63
  • 340
  • 553
  • 1
    I think you need to make your description of casting clearer, you can cast to a subtype if the object is that subtype. If you cast it to a type it isn't then you get an exception. – Keith Nicholas Sep 05 '19 at 22:19
  • also, for completeness, would be worth showing the new 'switch when' syntax if you want to handle multiple subtypes – Keith Nicholas Sep 05 '19 at 22:21
  • @KeithNicholas Great thought, added it. – Eric J. Sep 05 '19 at 22:36
  • Also, added a comment that the cast in the first example throws InvalidCastException. Thank you for pointing that out. – Eric J. Sep 05 '19 at 22:39
3

Use the other C# casting syntax, and use a recent C# feature (that allows associating a variable to the cast immediately):

bool AssignNums(Motor m)
{
   if (m is Title t) {
      //Do things with "t"
   }
}

If you do it this way, you ignore incoming m instances that are not of type Title. The is cast also never throws (neither does the related as operation).

Flydog57
  • 6,851
  • 2
  • 17
  • 18