abbattuto e ribaltato


88

Sono nuovo in C # (e OOP ). Quando ho un codice come il seguente:

class Employee
{
    // some code
}


class Manager : Employee
{
    //some code
}

Domanda 1 : se ho un altro codice che fa questo:

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

Ecco Employeeun Manager, ma quando lo lancio in questo Employeemodo significa che lo sto upcasting?

Domanda 2 :

Quando ho diversi Employeeoggetti classe e alcuni, ma non tutti, sono Manager, come posso abbatterli ove possibile?


6
L'upcasting può essere eseguito senza cast esplicito. Quindi Employee emp= mgr;dovrebbe essere sufficiente.
baciami l'ascella

Risposte:


93
  1. È corretto. Quando lo fai, lo lanci in un employeeoggetto, quindi ciò significa che non puoi accedere a nulla di specifico del gestore.

  2. Il downcasting è dove prendi una classe base e poi provi a trasformarla in una classe più specifica. Questo può essere ottenuto usando is e un cast esplicito come questo:

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

o con l' asoperatore come questo:

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

Se qualcosa non è chiaro sarò felice di correggerlo!


Ho bisogno di esempio per sapere cos'è il Downcasting?
user184805

4
Evita di ridefinire termini ben stabiliti: "boxing", nel contesto di OOP e C #, significa qualcosa di piuttosto diverso (= avvolgere un oggetto di tipo valore in un riferimento). Inoltre, il tuo esempio potrebbe (e dovrebbe) utilizzare l' asoperatore invece di is, seguito da un cast.
Konrad Rudolph

2
Sono stato corretto sul primo punto e ho cambiato la seconda metà della mia risposta per mostrare entrambi i modi di farlo.
RCIX

2
La tua prima affermazione ("... casting [un'istanza della classe Manager] in un oggetto" dipendente "[..] significa che non puoi accedere a nulla di specifico del manager") non è completamente accurata. Nell'esempio di OP, se Employee ha un membro virtuale che viene sovrascritto in Manager, il CLR chiamerà l'implementazione Manager, nonostante il cast. Dall'articolo di MSDN sul polimorfismo in C #: "Quando una classe derivata sostituisce un membro virtuale, quel membro viene chiamato anche quando si accede a un'istanza di quella classe come istanza della classe base". L'esempio fornito da MSDN è quasi identico.
Antony

49

L'upcasting (usando (Employee)someInstance) è generalmente facile in quanto il compilatore può dirti in fase di compilazione se un tipo è derivato da un altro.

Tuttavia, il downcasting deve essere eseguito generalmente in fase di esecuzione poiché il compilatore potrebbe non sapere sempre se l'istanza in questione è del tipo fornito. C # fornisce due operatori per questo: è che ti dice se il downcast funziona e restituisce vero / falso. E come che tenta di eseguire il cast e restituisce il tipo corretto se possibile, o null in caso contrario.

Per verificare se un dipendente è un manager:

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

Puoi anche usare questo

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
  • L'upcasting è un'operazione che crea un riferimento alla classe base da un riferimento alla sottoclasse. (sottoclasse -> superclasse) (cioè Manager -> Dipendente)
  • Il downcasting è un'operazione che crea un riferimento di sottoclasse da un riferimento di classe base. (superclasse -> sottoclasse) (cioè dipendente -> Manager)

Nel tuo caso

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

stai facendo un upcasting.

Un upcast riesce sempre a differenza di un downcast che richiede un cast esplicito perché può potenzialmente fallire in fase di esecuzione ( InvalidCastException ).

C # offre due operatori per evitare che questa eccezione venga generata:

A partire da:

Employee e = new Employee();

Primo:

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

Secondo:

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

Attenzione : quando esegui un upcast puoi accedere solo ai metodi, alle proprietà ecc. Della superclasse.


6

Nel caso in cui sia necessario controllare ciascuno degli oggetti Employee se si tratta di un oggetto Manager, utilizzare il metodo 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

Risposta 1: Sì, ha chiamato upcasting ma il modo in cui lo fai non è un modo moderno. L'upcasting può essere eseguito implicitamente, non è necessaria alcuna conversione. Quindi basta scrivere Employee emp = mgr; è sufficiente per l'upcasting.

Risposta 2: Se crei un oggetto della classe Manager, possiamo dire che il manager è un dipendente. Perché la classe Manager: Employee descrive la relazione Is-A tra Employee Class e Manager Class. Quindi possiamo dire che ogni manager è un dipendente.

Ma se creiamo un oggetto della classe Employee non possiamo dire che questo impiegato è manager perché la classe Employee è una classe che non eredita nessun'altra classe. Quindi non è possibile eseguire il downcast diretto di quell'oggetto Employee Class all'oggetto Manager Class.

Quindi la risposta è, se si desidera eseguire il downcast da un oggetto Employee Class a un oggetto Manager Class, prima è necessario disporre di un oggetto della classe Manager, quindi è possibile eseguire l'upcast e quindi è possibile eseguire il downcast.


-1

Upcasting e Downcasting:

Upcasting: Casting da Classe Derivata a Classe Base Downcasting: Casting da Classe Base a Classe Derivata

Comprendiamo lo stesso come un esempio:

Considera due classi Shape come classe genitore e Circle come classe derivata, definite come segue:

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; }
}

Upcasting:

Forma s = nuova forma ();

Cerchio c = s;

Sia c che s fanno riferimento alla stessa posizione di memoria, ma entrambi hanno viste diverse cioè usando il riferimento "c" puoi accedere a tutte le proprietà della classe base e anche della classe derivata ma usando il riferimento "s" puoi accedere alle proprietà dell'unica classe genitore.

Un esempio pratico di upcasting è la classe Stream che è la classe base di tutti i tipi di lettori di stream di .net framework:

Lettore StreamReader = nuovo StreamReader (nuovo FileStreamReader ());

qui, FileStreamReader () viene upcast in streadm reder.

Abbattimento:

Forma s = nuovo cerchio (); qui come spiegato sopra, la vista di s è l'unico genitore, per renderla sia per il genitore che per un figlio dobbiamo abbatterla

var c = (Circle) s;

L'esempio pratico di downcasting è la classe dei pulsanti di WPF.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.