2

I've got a simple question concerning upcasting in c#. For example I have two interfaces:

interface IUSer
{
    string UserName { get; set; }
}

interface IAdmin: IUSer
{
    string Password { get; set; }
}

...and a class implementing IAdmin interface:

class Admin : IAdmin
{
    public string Password { get; set; }
    public string UserName { get; set; }
}

When I create an object of type Admin and try to upcast it to IUser, technically I can then only access UserName user.UserName:

var admin = new Admin() { UserName = "Arthur", Password = "hello" };
var user = (IUSer)admin;
Console.WriteLine( user.UserName );

...but If I cycle through this object's properties using Reflection, like that:

    private static void Outputter(IUSer user)
    {
        foreach (var prop in user.GetType().GetProperties())
        {
            Console.WriteLine(prop.Name +  " " + prop.GetValue(admin));
        }
    }

...I can also see Password property. The question is - why it is saved when upcasted?

Artleks
  • 156
  • 2
  • 16
  • 1
    Would you like the CLR to delete them? that would make life difficult for everyone else in the world dont you think? the asnwer is so you can downcast again – TheGeneral Jun 27 '18 at 08:27
  • But what If I need to send an upcasted object through some kind of a transport protocol to a server or something for example, will Password property from this example be sent also? – Artleks Jun 27 '18 at 08:31
  • Possible duplicate of [How Upcasting preserve derived classes's Properties?](https://stackoverflow.com/questions/46115856/how-upcasting-preserve-derived-classess-properties) – Michał Turczyn Jun 27 '18 at 08:31
  • See @daisyShipton answer, nailed it – TheGeneral Jun 27 '18 at 08:32
  • 1
    also *But what If I need to send an upcasted object through some kind of a transport protocol to a server* is a completely different question really – TheGeneral Jun 27 '18 at 08:34
  • @TheGeneral I have seen such case, if we have the same Type defined on remote server, we can easily cast object back to original type. – Amit Jun 27 '18 at 08:52
  • @amit agreed, however this is more a serialization problem more than a casting one – TheGeneral Jun 27 '18 at 08:54
  • @ArthurBardakov what case you are saying, to reproduce such case and understand it's behaviour, you are not even required to implement interface hierarchy (as you shown in question), you just need to use non-generic collection. I bet you were doing this all the time. – Amit Jun 27 '18 at 08:56
  • @TheGeneral yes, that is true! – Amit Jun 27 '18 at 08:59
  • @amit Thanks, got it! – Artleks Jun 27 '18 at 09:00

2 Answers2

13

The question is - why it is saved when upcasted?

Because casting doesn't change the object at all. It just changes how you're viewing the object.

Think of it like being a person. You may have different ways that people can view you:

  • A colleague
  • A manager
  • A family member
  • A friend

They only "see" certain aspects of you, but that doesn't change who you are.

Likewise a simple reference conversion doesn't change the object. If you call user.GetType() it will still report the actual type of the object. It's just that when you view the object through a particular lens (whether that's an interface or a base class) you only see the members that lens shows you.

(Note that a cast that calls a user-defined conversion, e.g. casting from XElement to string, is entirely different. That returns a reference to a new object, rather than just regarding the existing object in a different way.)

If you only want to see the IUser properties, use typeof(IUser).GetProperties() instead of calling GetType() first:

private static void Outputter(IUser user)
{
    foreach (var prop in typeof(IUser).GetProperties())
    {
        Console.WriteLine($"{prop.Name}: {prop.GetValue(user)}");
    }
}

Although I'm not sure it's particularly useful to do that with reflection in most cases.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
1

when you cast the object of any type to their base type, you are just holding that object with they type of base.

object doesn't loos its properties by that.

If you see a simplest example : Use of non generic collection

when you add some object (let's say of Admin class) in ArrayList, you are actually converting that object into type object (Boxing) and then store it arraylist. So it is ultimate example of up-casting! How?

The object type is an alias for Object in the .NET Framework. In the unified type system of C#, all types, predefined and user-defined, reference types and value types, inherit directly or indirectly from Object.

Full Post

Now object type doesn't hold properties like userName password. So when you try to access those property from the object you get directly from arraylist, you will not able to do so. Because current you are dealing with the type object and you will get access only those properties or members which is supported by object type (but here you are not getting access, still those properties are there). In addition as note in other answer GetType() method will surely return it's original type too.

But when you get that original object back from array list by casting it back to Admin type (Unboxing) , you will see those properties are there in your object as they were before. Only thing which is changed is, now you are able to access them because Admin type supports them.

Read this for more detail

Amit
  • 1,821
  • 1
  • 17
  • 30