занижене і занижене


88

Я новачок у C #ООП ). Коли у мене є такий код, як наведений нижче:

class Employee
{
    // some code
}


class Manager : Employee
{
    //some code
}

Питання 1 : Якщо у мене є інший код, який робить це:

   Manager mgr = new Manager();
   Employee emp = (Employee)mgr;

Ось Employeeтакий Manager, але коли я його кидаю таким чином, Employeeце означає, що я його оновлюю?

Питання 2 :

Коли у мене є кілька Employeeоб’єктів класу, а деякі, але не всі, є Manager, як я можу їх знизити, де це можливо?


6
Оновлення можна здійснити без явного складання. Так Employee emp= mgr;повинно вистачити.
поцілуй мене в пахву

Відповіді:


93
  1. Це правильно. Коли ви робите це, ви кидаєте його в employeeоб'єкт, тож це означає, що ви не можете отримати доступ до будь-якого конкретного менеджера.

  2. Даункастінг - це місце, де ви берете базовий клас, а потім намагаєтесь перетворити його на більш конкретний клас. Цього можна досягти, використовуючи is і явний привід, подібний до цього:

    if (employee is Manager)
    {
        Manager m = (Manager)employee;
        //do something with it
    }
    

або з asоператором, як це:

Manager m = (employee as Manager);
if (m != null)
{
    //do something with it
}

Якщо щось незрозуміле, я із задоволенням це виправлю!


Мені потрібен приклад, щоб знати, що таке Downcasting?
user184805

4
Уникайте перевизначення усталених термінів: «бокс», в контексті ООП та С #, означає щось зовсім інше (= обертання об’єкта типу значення у посилання). Крім того, у вашому прикладі можна (і потрібно) використовувати asоператор замість is, за яким слідує привід.
Конрад Рудольф

2
Я стою виправлений на першому пункті, і я змінив другу половину своєї відповіді, щоб показати обидва способи зробити це.
RCIX

2
Ваше перше твердження ("... введення [екземпляра класу менеджера] в об'єкт" працівника "[..] означає, що ви не можете отримати доступ до будь-якого конкретного менеджера") не є повністю точним. У прикладі OP, якщо у працівника є віртуальний член, який замінено в диспетчері, CLR викличе реалізацію диспетчера, незважаючи на приведення. Зі статті MSDN про поліморфізм у C #: "Коли похідний клас замінює віртуальний член, цей член викликається, навіть якщо екземпляр цього класу отримує доступ як екземпляр базового класу." Приклад, наданий MSDN, майже ідентичний.
Антоній

49

Оновлення (використання (Employee)someInstance), як правило, просте, оскільки компілятор може сказати вам під час компіляції, якщо тип походить від іншого.

Однак зниження варто робити під час виконання, як правило, компілятор не завжди може знати, чи відповідає даний екземпляр типу. C # надає два оператори для цього - це те, що повідомляє вам, чи працює зниження, і повертає true / false. І як який намагається виконати приведення і повертає правильний тип, якщо це можливо, або нульовий, якщо ні.

Щоб перевірити, чи є працівник менеджером:

Employee m = new Manager();
Employee e = new Employee();

if(m is Manager) Console.WriteLine("m is a manager");
if(e is Manager) Console.WriteLine("e is a manager");

Ви також можете використовувати це

Employee someEmployee = e  as Manager;
    if(someEmployee  != null) Console.WriteLine("someEmployee (e) is a manager");

Employee someEmployee = m  as Manager;
    if(someEmployee  != null) Console.WriteLine("someEmployee (m) is a manager");

11
  • Upcasting - це операція, яка створює посилання на базовий клас із посилання на підклас. (підклас -> суперклас) (тобто менеджер -> працівник)
  • Зниження - це операція, яка створює посилання на підклас із посилання на базовий клас. (суперклас -> підклас) (тобто працівник -> менеджер)

У вашому випадку

Employee emp = (Employee)mgr; //mgr is Manager

ви робите оновлення.

Оновлення завжди успішне, на відміну від даундасту, який вимагає явного приведення, оскільки він може потенційно зазнати збою під час виконання. ( InvalidCastException ).

C # пропонує два оператори, щоб уникнути цього виключення:

Починаючи з:

Employee e = new Employee();

Спочатку:

Manager m = e as Manager; // if downcast fails m is null; no exception thrown

Друге:

if (e is Manager){...} // the predicate is false if the downcast is not possible 

Попередження : Коли ви робите оновлення, ви можете отримати доступ лише до методів, властивостей суперкласу тощо ...


6

Якщо вам потрібно перевірити кожен об’єкт Employee, чи є він об’єктом Manager, використовуйте метод OfType:

List<Employee> employees = new List<Employee>();

//Code to add some Employee or Manager objects..

var onlyManagers = employees.OfType<Manager>();

foreach (Manager m in onlyManagers) {
  // Do Manager specific thing..
}

2

Відповідь 1: Так, це викликало оновлення, але те, як ви це робите, не є сучасним. Оновлення можна виконати неявно, вам не потрібно перетворення. Тож просто писати Employee emp = mgr; достатньо для оновлення.

Відповідь 2: Якщо ви створюєте об'єкт класу Manager, ми можемо сказати, що менеджер - це працівник. Тому що менеджер класу: Співробітник зображує відносини Is-A між класом працівника та класом менеджера. Тож можна сказати, що кожен менеджер - це працівник.

Але якщо ми створюємо об'єкт класу Employee, ми не можемо сказати, що цей співробітник є менеджером, оскільки клас Employee - це клас, який не успадковує жодного іншого класу. Таким чином, ви не можете безпосередньо знизити цей об'єкт Class Employee до об'єкта Class Manager.

Отже, відповідь полягає в тому, що якщо ви хочете перейти з об’єкта класу працівника на об’єкт класу менеджера, спочатку ви повинні спочатку мати об’єкт класу менеджера, потім ви можете оновити його, а потім ви можете його знизити.


-1

Поповнення та зниження:

Оновлення: Кастинг з похідного класу на базовий клас Даундастінг: Кастинг з базового класу на похідний клас

Давайте розберемо те саме як приклад:

Розглянемо два класи Shape як мій батьківський клас і Circle як похідний клас, визначені таким чином:

class Shape
{
    public int Width { get; set; }
    public int Height { get; set; }
}

class Circle : Shape
{
    public int Radius { get; set; }
    public bool FillColor { get; set; }
}

Оновлення:

Shape s = new Shape ();

Коло c = s;

І c, і s посилаються на одне і те ж розташування пам'яті, але обидва вони мають різні види, тобто, використовуючи посилання "c", ви також можете отримати доступ до всіх властивостей базового класу та похідного класу, але, використовуючи посилання "s", ви можете отримати доступ до властивостей єдиного батьківського класу.

Практичним прикладом оновлення є клас Stream, який є базовим класом усіх типів пристрою для зчитування потоків .net framework:

Пристрій читання StreamReader = новий StreamReader (новий FileStreamReader ());

тут FileStreamReader () оновлено для відтворення Streadm.

Даундайтинг:

Фігура s = нове коло (); тут, як пояснено вище, подання s є єдиним батьком, щоб зробити його як для батьків, так і для дитини, нам потрібно його знизити

var c = (Коло) s;

Практичним прикладом Downcasting є клас кнопок WPF.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.