Quali sono alcuni usi pratici del modificatore "nuovo" in C # rispetto al nascondimento?

21

Un collega e io stavamo osservando il comportamento della parola chiave new in C # in quanto si applica al concetto di nascondimento. Da documentazione :

Use the new modifier to explicitly hide a member inherited from a base class. To hide an inherited member, declare it in the derived class using the same name, and modify it with the new modifier.

Abbiamo letto la documentazione e abbiamo capito cosa fa e come funziona. Ciò su cui non siamo riusciti a capire è perché dovresti farlo in primo luogo. Il modificatore è presente dal 2003 e abbiamo lavorato con .Net più a lungo e non è mai stato pubblicato.

Quando sarebbe necessario questo comportamento in senso pratico (ad es. applicato a un caso aziendale)? Si tratta di una funzionalità che è sopravvissuta alla sua utilità o che è abbastanza rara in ciò che facciamo (in particolare facciamo moduli Web e applicazioni MVC e alcuni piccoli fattori WinForm e WPF)? Nel provare questa parola chiave e nel giocarci, abbiamo trovato alcuni comportamenti che consentono di sembrare un po 'pericolosi se usati in modo improprio.

Sembra un po 'aperto, ma stiamo cercando un caso d'uso specifico che possa essere applicato a un'applicazione aziendale che trovi utile questo particolare strumento.

    
posta Joel Etherton 21.06.2012 - 14:11
fonte

5 risposte

22

Puoi usarlo per imitare la covarianza del tipo di ritorno. Spiegazione di Eric Lippert . Eric fornisce questo codice di esempio:

abstract class Enclosure
{
    protected abstract Animal GetContents();
    public Animal Contents() { return this.GetContents(); }
}
class Aquarium : Enclosure
{
    public new Fish Contents() { ... }
    protected override Animal GetContents() { return this.Contents(); }
}

Questa è una soluzione. public Fish Contents() { ... } non è legale, nonostante sia sicuro.

In generale, dovresti non utilizzare il metodo hiding, poiché confonde i consumatori della tua classe (l'esempio specifico sopra non soffre di questo problema). Basta nominare il nuovo metodo qualcos'altro se non si vuole sovrascrivere un metodo esistente.

Una probabile situazione del mondo reale in cui è necessario nascondere il metodo è se il fornitore di una classe base ha aggiunto un metodo generico che era già stato aggiunto a una classe derivata. Tale programma compilerà (e darà avvertimenti) senza la nuova parola chiave, ma aggiungendo new dice "So che la mia versione di questo metodo sta sostituendo la versione della classe base. Questo è orribile e confuso, ma siamo bloccati ". È ancora meglio che forzare la classe derivata a rinominare il loro metodo.

Il solo fatto che il metodo derivato venga trattato come un override potrebbe causare problemi. Ignorando qualsiasi problema con l'implementazione del compilatore, il nuovo metodo è semanticamente diverso dal metodo base, ma il polimorfismo causerebbe il richiamo del nuovo metodo quando viene richiesto di chiamare un metodo con lo stesso nome.

Questa situazione è discussa in dettaglio in questo post di Eric Lippert.

    
risposta data 21.06.2012 - 15:17
fonte
4

Penso che ci sia nel caso in cui potresti aver bisogno di fare qualcosa a cui i progettisti linguistici potrebbero non aver pensato. C # è stata per molti versi una reazione alle prime versioni di Java. E una cosa che ha fatto java è stato per gli sviluppatori molto esplicitamente incasellati per eliminare le possibilità degli sviluppatori di spararsi ai piedi. C # ha adottato un approccio leggermente diverso e ha dato agli sviluppatori un po 'più di potenza nel permettere agli sviluppatori di avere qualche possibilità in più di spararsi in piedi. Un esempio è la parola chiave unsafe . Questa parola chiave new è un'altra.

Ora, probabilmente non è così utile come unsafe ma una volta entrato in una specifica del linguaggio è difficile uscire da una specifica della lingua.

    
risposta data 21.06.2012 - 14:29
fonte
3

Sta dicendo al lettore che "ho deliberatamente nascosto l'implementazione della classe base di questo metodo", invece che accidentalmente.

    
risposta data 21.06.2012 - 14:50
fonte
0

Potresti voler rendere disponibile il precedente membro tramite un altro nome:

class VehicleClass
{
  public int AnyProperty
  {
    get; set;
  }

  public int AnyFunction() { return 0; }
} // VehicleClass

class IntermediateClass : VehicleClass
{
  public int PreviousAnyProperty
  {
    get { return AnyProperty; }
    set { AnyProperty = value  }
  }

  public int PreviousAnyFunction() { return AnyFunction(); }
} // IntermediateClass 

class CarClass : IntermediateClass
{
  public new int AnyProperty
  {
    get ; set ;
  }

  public new int AnyFunction() { return 5; }
} // class CarClass

class ExampleClass
{

  public static void Main()
  {
    using (CarClass MyCar = new CarClass())
    {
      int AnyInt1 = MyCar.PreviousAnyProperty;
      MyCar.PreviousAnyProperty = 7;

      int AnyInt2 = MyCar.PreviousAnyFunction();

      int AnyInt3 = MyCar.AnyProperty;
      MyCar.AnyProperty = 45;

      int AnyInt4 = MyCar.AnyFunction();
    }
  } // static void Main()

} // class CarClass

Saluti.

    
risposta data 21.06.2012 - 19:08
fonte
0

L'ho trovato abbastanza utile durante la creazione di una suite di test per il codice legacy. Mi permette di nascondere dipendenze esterne, come interrogare un database all'interno di un metodo che viene utilizzato da altri metodi. Per poter testare gli altri metodi, posso nascondere la logica originale che dipende dalle risorse esterne senza dover aggiungere la parola chiave virtuale a quei metodi nelle classi di test.

    
risposta data 22.07.2015 - 17:52
fonte

Leggi altre domande sui tag