Нужна помощь, чтобы понять полиморфизм

#c# #polymorphism

#c# #полиморфизм

Вопрос:

Классы, приведенные ниже, состоят из

A — класс отца

B — дочерний класс

Держатель — Содержит список A

Я хочу получить доступ к дочернему свойству из списка объектов-отцов. Почему я не могу этого сделать? Или лучший вопрос, как мне это сделать?

 public class A
{
    public int var = 0;
}

public class B : A
{
    public int Property1 { get; set; }
    public int Property2 { get; set; }

    public B()
    {

    }

    public B(B p_B)
    {
        Property1 = p_B.Property1;
        Property2 = p_B.Property2;
    }
}

class Holder
{
    private List<A> m_Objects = new List<A>();

    public void AddObject(A p_Object)
    {
        m_Objects.Add(p_Object);
    }

    public void AddObjectProperty1(B p_B)
    {
        // At this point, m_Objects holds a B-object. And I want to add the value from Property1
        // but there is no Property1 in the A-class so I cant do this. How do I use the base.values from 
        // a statement like the one below?
        int index = m_Objects.FindIndex(item => item.Property1 == p_B.Property1);
        if (index > -1)
            m_Objects.ElementAt(index).Property1  = p_B.Property1;
    }
}


class Program
    {
        static void Main(string[] args)
        {
            // Class to hold the objects
            Holder h = new Holder();

            // Create a B object
            B b = new B();
            b.Property1 = 1;
            b.Property2 = 2;

            // Place a new instance of the B-object in a list of A's
            h.AddObject(new B(b));

            // Add the value from Property1 to the value in the b-object in the a-list.  :P
            h.AddObjectProperty1(b);

            Console.WriteLine(  b.var);
            Console.ReadLine();


        }
    }
 

Комментарии:

1. Не называйте свою переменную var . Во-первых, это ничего не значит, во-вторых, var это также ключевое слово в C # — ваш код станет беспорядочным и сложным в обслуживании.

2. Да, спасибо за ваш совет! 🙂 Я обычно не называю переменные var, я просто пытался создать что-то максимально общее в этом конкретном случае! Но спасибо, что заметили это!

3. Почему вопрос отклонен? 🙁

Ответ №1:

Вы можете использовать приведение типов:

 (m_Objects[i] as B).Property1
 

Или

 ((B)m_Objects[i]).Property1
 

Комментарии:

1. Я за тебя отвечаю! Я попробовал это решение, но свойство 1 не распознается, даже если приведение типов правильное. 🙁

2. Что значит: не распознано. Он не компилируется или не завершается с ошибкой, или вы получаете нулевое значение?

Ответ №2:

Во время компиляции у компилятора нет возможности узнать, вы бы только добавили B s в свой список A s. Таким образом, нет никакой гарантии, что каждый item из следующих запросов является экземпляром B и, следовательно, имеет Property1

 int index = m_Objects.FindIndex(item => item.Property1 == p_B.Property1);
 

Первая возможность — это приведение, как в ответе Артема. Но это не удастся, если вы не все элементы в списке действительно B s. Итак, если вы полагаетесь на все элементы в m_Objects , чтобы быть экземплярами B , почему бы вам просто не использовать List<B> m_Objects ?

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

 int index = m_Objects.FindIndex(item => (item is B) amp;amp; (item as B).Property1 == p_B.Property1);
 

Смотрите этот пример DotNetFiddle

Комментарии:

1. Это именно то, что я искал. Причина, по которой я хочу хранить B в A, а не наоборот, заключается в том, что я хочу использовать полиморфизм для хранения объектов таким образом, который я нахожу разумным (что может быть не так). Например, если holderclass является кошельком. Я хочу хранить наличные деньги (читается как A), которые могут быть в виде монет или банкнот (B или C, если C существует). Звучит это хорошо для меня, так как я могу просто иметь список наличных денег. Я попробовал ваше решение, и синтаксис был правильным, однако свойство 1 не найдено при приведении элемента: (Есть какие-нибудь подсказки? Я думаю об этом неправильно?

2. С этой точки зрения использование a List<A> имеет смысл. Что вы подразумеваете под «Property1 не найден»? Смотрите обновленную скрипку . Кажется, работает так, как ожидалось.