0

I have base class perDat. I have class mPerDat that derives from perDat. I also have class iPerDat class that derives from perDat. Two files that represent the mPerDat and iPerDat are exactly the same different only in class names and types, both inherit after perDat directly. And now the code:

mPerDat mPerDatObj = perDatObj as mPerDat;
iPerDat iPerDatObj = perDatObj as iPerDat;

if (mPerDatObj != null)
    { do something with mPerDatObj }
if (iPerDatObj != null)
    { do something with iPerDatObj }

The strange thing is, that mPerDatObj have nice object after casting, but the iPerDatObj does not. Where should I search for the problem?

pbies
  • 666
  • 11
  • 28
  • what do you mean by "mPerDatObj have nice object after casting"?? – Karim AG Mar 30 '14 at 13:11
  • It does have the object I need. Casting succeeds. – pbies Mar 30 '14 at 13:15
  • 1
    That's exactly what should happen. Why would you expect anything else? mPerDat and iPerDat are different classes and neither one derives from the other so any object can only be one type or the other, not both. Just because two types have the same members doesn't make them the same type. Two different types are two different types and that's that. – jmcilhinney Mar 30 '14 at 13:18
  • I would expect that before this code I have object of iPerDat type and that it will cast to this type. Should I look into other code, that gives the type, not exactly here? – pbies Mar 30 '14 at 13:22
  • Most c# programmers will find your class names very confusing. Class names should begin with a Capital letter, and names starting with 'I' should be avoided and used for Interfaces, not Classes. http://stackoverflow.com/questions/1618316/naming-convention-in-c-sharp – hatchet - done with SOverflow Mar 30 '14 at 13:27
  • Presented code is only for question, in the real app it is ok - I needed to change the names (confidential). – pbies Mar 30 '14 at 13:32
  • That's fine, but it makes your question's sample code more difficult to read, and distracts from the issue you're asking about. – hatchet - done with SOverflow Mar 30 '14 at 13:34
  • I'll remember that for the next question. – pbies Mar 30 '14 at 13:36

2 Answers2

2

You are having a wrong concept about inheritance and type casting. What you have is:

class PerDat
class mPerDat : PerDat
class iPerDat : PerDat

so a given instance can either be a mPerDat instance or a iPerDat instance, but not both at the same time. When you cast the reference to that instance, one of them must turn out to be null. I am not sure what you're trying to do, but I'd bet you want to cast to PerDat instead.

Analogy:

class Human
class Male : Human
class Female : Human

if you use the Human() constructor you get a Human instance, the Male() constructor gets you a Male instance, and the Female() constructor gets you a Female instance. Both Female and Male inherit Human directly, but obviously you cannot cast one to the other. You can, however, treat them all as Human instances.

kevin
  • 2,196
  • 1
  • 20
  • 24
  • Very close, but... I try to cast to one type, then the other, if all the casting don't succeed I'll cast to PerDat. But I know earlier that object can be casted to mPerDat and it cast to that type, and that it does not cast to iPerDat - but it should. – pbies Mar 30 '14 at 13:20
  • No, it shouldn't. It's one or the other, not both. – Enigmativity Mar 30 '14 at 13:25
  • Ok, so I should look earlier for what gives the type? – pbies Mar 30 '14 at 13:26
  • No it should not. You don't get the point... if that object can be casted to mPerDat that means it is a mPerDat instance, which logically implies that it can NEVER be treated like a iPerDat instance. If it can be casted to mPerDat then there's 100% probability that it cannot be casted to iPerDat. – kevin Mar 30 '14 at 13:26
  • Ok, so what if the object is iPerDat and it does not cast? It should cast then, right? Or what if it is not the iPerDat type nor even mPerDat? – pbies Mar 30 '14 at 13:29
  • 1
    Try this: A Human is a Human. A Male is a Human. A Female is also a Human. But Male is NEVER Female, and Female is NEVER Male. – kevin Mar 30 '14 at 13:29
  • I understand that, but I cannot understand why iPerDat type object does not cast to this type. This seems to be other place, that the object is made and it does not have iPerDat type. – pbies Mar 30 '14 at 13:30
  • 1
    if it casts to null then it means that object is not iPerDat type. It can be anything but iPerDat. And by the way, if you set a breakpoint in visual studio and hover your mouse on the variable you can see exactly what that object is. – kevin Mar 30 '14 at 13:32
  • Great! I understand now, that I need to search other place for the source of the type given. – pbies Mar 30 '14 at 13:33
0

Concentrate on below two lines

mPerDat mPerDatObj = perDatObj as mPerDat;

Here you are casting perDatObj to mPerDat

Then in the below line you are trying to cast it to iPerDat which is not possible cause there is no relationship between them. So it fails in casting.

iPerDat iPerDatObj = perDatObj as iPerDat;

Just to check, after you cast it to perDatObj as mPerDat; do a perDatObj.Gettype() and it will of type mPerDat and there is no way of casting it to iPerDat on the fly (Same as you can't cast/convert yourself to me cause we both are different entity altogether having different characteristics)

Rahul
  • 76,197
  • 13
  • 71
  • 125
  • There are few classes and few invokes of this code, the types differ. And the code is casting to mPerDat, but does not cast to iPerDat. – pbies Mar 30 '14 at 13:23
  • it should not moreover, just try `iPerDat iPerDatObj = perDatObj as iPerDat;` without other line and it will success. – Rahul Mar 30 '14 at 13:25
  • I can't do that. I need to recognize the type and use the proper object type. – pbies Mar 30 '14 at 13:27
  • For the edit: the object sometimes have one type, sometimes the other. – pbies Mar 30 '14 at 13:35
  • 1
    Yes but only if there is a relationship b/w them otherwise not/never. – Rahul Mar 30 '14 at 13:36