Понижение и повышение

Я новичок в С# (и OOP). Когда у меня есть код вроде следующего:

class Employee
{
    // some code
}


class Manager : Employee
{
    //some code
}

Вопрос 1: Если у меня есть другой код, который делает это:

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

Здесь Employee есть Manager, но когда я делаю это как Employee, это означает, что я его повышаю?

Вопрос 2:

Когда у меня есть несколько объектов класса Employee, а некоторые, но не все из них, являются Manager, как я могу их преуменьшать, если это возможно?

Ответ 1

  • Это правильно. Когда вы делаете это, вы бросаете его в объект "employee", так что это означает, что вы не можете получить доступ к каким-либо конкретным менеджерам.

  • Downcasting - это место, где вы берете базовый класс, а затем пытаетесь превратить его в более конкретный класс. Это может быть выполнено с использованием 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
}

Если что-то неясно, я буду рад исправить его!

Ответ 2

Ускорение (с использованием (Employee)someInstance) обычно легко, поскольку компилятор может рассказать вам во время компиляции, если тип получен из другого.

Downcasting, однако, должно выполняться во время выполнения, как правило, поскольку компилятор может не всегда знать, относится ли данный экземпляр указанного типа. С# предоставляет для этого два оператора - -, который сообщает вам, работает ли downcast, и возвращает true/false. И как, который пытается выполнить приведение и возвращает правильный тип, если это возможно, или null, если нет.

Чтобы проверить, является ли сотрудник менеджером:

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");

Ответ 3

Если вам нужно проверить каждый из объектов Employee, является ли он объектом-менеджером, используйте метод 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..
}

Ответ 4

  • Upcasting - это операция, которая создает ссылку базового класса из ссылки подкласса. (подкласс → суперкласс) (т.е. Менеджер → Сотрудник)
  • downcasting - это операция, которая создает ссылку подкласса из ссылки базового класса. (суперкласс → подкласс) (т.е. Employee → Manager)

В вашем случае

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

вы делаете повышение.

В отличие от downcast, который требует явного приведения, он всегда преуспевает, потому что он может потенциально сбой во время выполнения. (InvalidCastException).

С# предлагает два оператора, чтобы исключить это исключение:

Начиная с:

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 

Warnign. Когда вы делаете upcast, вы можете получить доступ только к методам, свойствам и т.д. superclass...