Domanda

Ho due classi:

public class MyBase
{
    public virtual void DoMe()
    {

    }
}

public class MyDerived:MyBase
{
    public override void DoMe()
    {
        throw  new NotImplementedException();
    }
}

E ho il seguente codice per istanziare MyDerived:

        MyDerived myDerived=new MyDerived();

La cosa è come chiamare DoMe della classe base? Se uso myDerived.DoMe (), verrà chiamato il metodo derivato, risultante in un'eccezione. Ho provato a trasmettere myDerived a MyBase, ma è ancora la versione derivata del metodo che viene chiamata.

Modifica: come menzionato nel commento qui sotto, non posso cambiare eitehr MyDerived o MyBase perché non sono il mio codice.

È stato utile?

Soluzione

C'è una soluzione, ma è brutta: usa la riflessione per ottenere il metodo di classe base, quindi emetti l'IL necessario per chiamarlo. Dai un'occhiata a questo post sul blog che illustra come fare Questo. Ho usato con successo questo approccio per chiamare l'implementazione della classe base di un metodo quando tutto ciò che ho è un riferimento a una classe derivata che sovrascrive quel metodo.

Altri suggerimenti

Non puoi chiamare la versione della classe base.

Se il metodo non funziona sulla classe derivata, è piuttosto improbabile che la versione base del metodo funzioni quando viene chiamata su un'istanza della classe derivata. Questo è solo chiedere guai. La classe non è stata progettata per funzionare in questo modo, e ciò che stai cercando di fare causerà probabilmente comportamenti imprevedibili di altre parti della classe.

Perché è necessario chiamare questo metodo sull'oggetto quando l'oggetto ti dice apertamente che non funzionerà?

Mi sembra che queste classi presentino alcuni difetti di progettazione e, se non ti è permesso di cambiarle, forse ti è permesso cambiare in una libreria più ben progettata.

Per chiamare MyBase.DoMe () da una classe esterna è necessario disporre di un'istanza di MyBase o di un'istanza derivata che non sovrascriva DoMe (). Un metodo dichiarato come virtuale verrà chiamato sul tipo di runtime effettivo dell'oggetto, non sul tipo di oggetto, motivo per cui il casting su MyBase non modifica il metodo chiamato. Se tuttavia il metodo non fosse dichiarato in MyBase come virtuale e MyDerived implementasse ancora DoMe () sarebbe "nascondere" " l'implementazione di MyBase. Pertanto, se il riferimento fosse MyDerived, chiamerebbe MyDerived.DoMe (), ma in questo caso eseguire il casting su MyBase myBase = (MyBase) myDerived e quindi chiamare myBase.DoMe () chiamerebbe MyBase.DoMe ().

La classe derivata non deve fornire un'implementazione del metodo. Rimuoverlo e l'implementazione nella classe base verrà chiamata per impostazione predefinita.

Se, a differenza del tuo esempio, il metodo nella classe base è astratto e devi fornire un'implementazione ma non ha senso per la classe derivata fornirne una, allora probabilmente c'è qualcosa di sbagliato nel design delle classi.

public class MyDerived:MyBase{    
    public override void DoMe()    
    {        
        base.DoMe();
    }
}

Modifica

Non puoi accedere al metodo delle classi di base da " outside " senza passare attraverso il metodo delle sottoclassi. L'unica opzione è creare un'istanza della classe base direttamente e chiamarne il metodo.

MyBase mb = new MyBase();
mb.DoMe();

Date le tue restrizioni, esiste un'altra possibilità:

Scarica .Net Reflector. Decompilare il codice esistente quindi apportare le modifiche necessarie per supportare la propria situazione.

Naturalmente, rivedi la legalità di questo prima di continuare.

Questa domanda è così vecchia ma non vedo la seguente opzione:

È possibile utilizzare la parola chiave "new" per specificare i metodi di sovrapposizione. Quindi esegui semplicemente il cast alla classe di cui desideri chiamare il metodo.

    public class MyBase
    {
        public virtual void DoMe()
        {

        }
    }

    public class MyDerived:MyBase
    {
//note the use of 'new' and not 'override'
        public new void DoMe()
        {
            throw  new NotImplementedException();
        }
    }

Implementazione

var myDerived = new MyDerived();
var derivedDoMe = myDerived.DoMe();
var baseDoMe = ((MyBase)myDerived).DoMe();
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top