0

Here is my example:

public class Person
{
    public string Name { get; set; }
}

public class Client : Person
{
    public string LastName { get; set; }
}

public class Test
{
    Person p = new Person();
    Client c = (Client)p; //throws exception
}

Since Client inherits from Person, why i can't do this? if i can and this is the wrong way, how can i do it?

OBS: I am aware that the example above will do:

Person p = new Client();
Client c = (Client)p;
9
  • 2
    What exception is thrown? Commented Jan 6, 2015 at 23:20
  • 2
    In your first example, if it did work what should happen when you do c.LastName? Commented Jan 6, 2015 at 23:20
  • 6
    See it this way: "all clients are persons but not all persons are clients"; hence, the compiler cannot be sure if the person you are trying to convert is indeed a client.
    – Josh Part
    Commented Jan 6, 2015 at 23:21
  • If this would work, using the c.LastName property would access memory that does not belong to the object. Since Person doesn't have that property. The gravest possible type safety problem you could imagine. That is how you corrupt a heap and make your program fail in impossible to diagnose ways. Commented Jan 6, 2015 at 23:23
  • 1
    @HansPassant - So you are saying there is a chance :P
    – Travis J
    Commented Jan 6, 2015 at 23:24

5 Answers 5

5

Actually with a little detour, you could make such a conversion work, however, it requires an extra parent class for both other classes, and an implicit operator to turn a Client into a Person (though this might not be what you were originally after)

class Program
{
    public abstract class BasePerson
    {
        public string FirstName { get; set; }
    }

    public class Person : BasePerson
    {
    }

    public class Client : BasePerson
    {
        public string LastName { get; set; }

        public static implicit operator Client(Person p)
        {
            if (p == null)
            {
                return null;
            }
            return new Client { FirstName = p.FirstName };
        }
    }

    static void Main(string[] args)
    {
        Person p = new Person { FirstName = "Test" };
        Client c = (Client)p;
        Console.WriteLine(c.FirstName);
        Console.ReadLine();
    }
}

which would compile and offer the FirstName to a client, with a last name possibility, however, as i said, this might not be what you were after, just a possibility to make your code compile, and run with minimal changes...

UPDATE

As discussed in the comments, if i would need to implement such a conversion, i would prefer doing it by either

  • Creating a helper method

    public class Client : Person
    {
        public static Client GetClientFromPerson(Person p) 
        {
            if (p == null) 
            {
                return null;
            }
            return new Client { FirstName = p.FirstName };
        }
    }
    

which would result in:

Client c = Client.GetClientFromPerson(p);
  • Adding a second constructor

    public class Client : Person
    {
        public string LastName { get; set; }
    
        public Client()
        {
        }
    
        public Client(Person p) : this()
        {
            FirstName = p.FirstName;
        }
    }
    

which would result in:

Client c = new Client(p);

This would make reviewing the code by somebody else a lot easier, also possible maintenance in the future, and wouldn't require you to change the inheritance that you have now

5
  • But as per the problem Person is a parent class and client is the child class, what is the reason of introducing a new parent class BasePerson? Commented Jan 7, 2015 at 0:11
  • @NitinAggarwal: it is necessary because otherwise you can also not compile, as you cannot make an implicit/explicit operator from or to a BaseClass. This was in essence just a trick to make it work, as i said, it might not have been what the OP was after, just a solution to make the code compilable + to enable the (Client)p statement
    – Icepickle
    Commented Jan 7, 2015 at 0:14
  • I appreciate your answer, i think what Fabio asked was different what you have answered, you have removed parent-child relationship between person and client. Commented Jan 7, 2015 at 0:21
  • @NitinAggarwal I agree with you on that one, and i also mentioned it in the answer and in the comments, in his case i would choose to create rather a helper method like Client GetClientFromPerson(Person p)to make it clear to other persons that this isn't a cast and it is rather a conversion, or a constructor with public Client(Person p) but, i thought i would try thinking out of the box on this one :)
    – Icepickle
    Commented Jan 7, 2015 at 0:25
  • I would vote up but i don't have enough reputation yet. Hehe. Commented Jan 7, 2015 at 2:50
0

A Person is not a Client hence how do you expect the compiler to cast it? Try this and you will get a null assigned:

Client c = p as Client;

In other words: compiler error gone, but c will always be null.

1
  • I thought that since Client inherits Person, when you try to cast the framework would do thejob of filling Client's Name property with the value of Person's Name Property. But its ok i got it, thanks for your time :D. Commented Jan 6, 2015 at 23:39
0

This throws an exception, because p is not a client. p has been created as person. You could create a client-object and cast it to its baseclass person, but not this way round.

1
  • I thought that since Client inherits Person, when you try to cast the framework would do thejob of filling Client's Name property with the value of Person's Name Property. But its ok i got it, thanks for your time :D. Commented Jan 6, 2015 at 23:37
0

A child can inherit all the properties of its parent class, but parent can only inherit common properties. that does not means you can assign directly parent object to it's child object.

0

you can do it by using as and is operatos.

By using as operator, if variable is not null then the class convertible to other class

Person p = new Person();
var conversionResultFromPersonToClient = p as Client;
if(conversionResultFromPersonToClient != null)
   //it means you can cast from person to client

Second way is using is operator

Person p = new Person();
Client c = new Client();
if(p is Client)
   //Then you can cast person to client
   c = (Client)p;

Not the answer you're looking for? Browse other questions tagged or ask your own question.