Почему объект сохраняет свойства при возврате - PullRequest
0 голосов
/ 27 июня 2018

У меня есть простой вопрос относительно апкастинга в c #. Например, у меня есть два интерфейса:

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

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

... и класс, реализующий интерфейс IAdmin:

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

Когда я создаю объект типа Admin и пытаюсь выгружать его в IUser, технически я могу получить доступ только к UserName user.UserName:

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

... но если я перебираю свойства этого объекта с помощью Reflection, вот так:

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

... Я также вижу свойство Password. Вопрос в том, почему это сохраняется, когда выгружается?

Ответы [ 2 ]

0 голосов
/ 27 июня 2018

когда вы приводите объект любого типа к его базовому типу, вы просто удерживаете этот объект с базовым типом.

объект не теряет при этом свои свойства.

Если вы видите самый простой пример: Использование не универсальной коллекции

когда вы добавляете какой-либо объект (скажем, класса Admin) в ArrayList, вы фактически конвертируете этот объект в тип object (бокс) и затем сохраняете его в виде массива. Так что это лучший пример приведения! Как?

Тип объекта является псевдонимом для объекта в .NET Framework. В унифицированной системе типов C # все типы, предопределенные и определяемые пользователем, ссылочные типы и типы значений, наследуются прямо или косвенно от Object.

Полный пост

Теперь тип object не содержит таких свойств, как userName password. Поэтому, когда вы пытаетесь получить доступ к этому свойству из объекта, который вы получаете непосредственно от arraylist, вы не сможете это сделать. Поскольку в настоящее время вы имеете дело с типом object, и вы получите доступ только к тем свойствам или элементам, которые поддерживаются типом object (но здесь вы не получаете доступ, все же эти свойства есть). Кроме того, как отмечено в другом ответе, метод GetType() обязательно вернет и его оригинальный тип.

Но когда вы вернете этот исходный объект из списка массивов, приведя его обратно к типу Admin (распаковка), вы увидите, что эти свойства есть в вашем объекте, как и прежде. Единственное, что изменилось, теперь вы можете получить к ним доступ, потому что тип Admin поддерживает их.

Подробнее читайте

0 голосов
/ 27 июня 2018

Вопрос в том, почему он сохраняется при возврате?

Поскольку приведение не меняет объект . Это просто меняет то, как вы просматриваете объект.

Думайте об этом, как о человеке. У вас могут быть разные способы просмотра вас:

  • Коллега
  • Управляющий
  • Член семьи
  • друг

Они только "видят" определенные аспекты вас, но это не меняет того, кто вы есть.

Аналогично, простое преобразование ссылок не меняет объект. Если вы позвоните user.GetType(), он все равно сообщит о фактическом типе объекта. Просто, когда вы просматриваете объект через определенный объектив (будь то интерфейс или базовый класс), вы видите только те элементы, которые вам показывает объектив.

(Обратите внимание, что приведение, которое вызывает пользовательское преобразование, например приведение от XElement к string, совершенно другое. Оно возвращает ссылку на новый объект, а не только на существующий объект в другом способ.)

Если вы хотите видеть только свойства IUser, используйте typeof(IUser).GetProperties() вместо вызова GetType() сначала:

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

Хотя я не уверен, что в большинстве случаев это особенно полезно делать с отражением.

...