2010-07-15 11 views
15

codice di esempio tratto da MSDNperché Object.GetType() non è virtuale?

public class Test { 
public static void Main() { 
    MyBaseClass myBase = new MyBaseClass(); 
    MyDerivedClass myDerived = new MyDerivedClass(); 
    object o = myDerived; 
    MyBaseClass b = myDerived; 

    Console.WriteLine("mybase: Type is {0}", myBase.GetType()); 
    Console.WriteLine("myDerived: Type is {0}", myDerived.GetType()); 
    Console.WriteLine("object o = myDerived: Type is {0}", o.GetType()); 
    Console.WriteLine("MyBaseClass b = myDerived: Type is {0}", b.GetType()); }} 

/* 
This code produces the following output. 
mybase: Type is MyBaseClass 
myDerived: Type is MyDerivedClass 
object o = myDerived: Type is MyDerivedClass 
MyBaseClass b = myDerived: Type is MyDerivedClass 
*/ 

Quindi sarebbe logico fare GetType() virtuale almeno funziona come virtuale? Qualcuno può spiegarlo? E altra domanda C'è qualche altro metodo nel framework NET che abbia un comportamento simile a GetType?

risposta

16

perché .Net framework non vuole che si sostituisca il metodo GetType() e spoof al tipo.

si supponga di poter sovrascrivere il metodo che altro si vorrebbe che facesse diversamente da restituire il tipo dell'istanza. e quando si sostituisce il metodo per ciascuna delle classi per restituire il tipo dell'istanza, non si viola quindi DRY.

+3

e ragionevolmente così! –

+0

si. hai ragione. ma potresti sovraccaricare questo metodo pubblico nella classe derivata)) – Arseny

+2

@Arseny: Quindi non è uguale a GetType() come definito nel tipo di oggetto. –

2

GetType restituisce il tipo effettivo dell'oggetto. Questo ci permette di sapere quale oggetto siamo veramente passati alla funzione "nostra". Molti metodi del framework hanno bisogno di questo per determinare le proprie funzionalità - nella maggior parte dei casi per ottenere gli Attributi di questa classe. Se il Framework perderebbe la possibilità di determinare il tipo reale di un oggetto, l'oggetto perderebbe anche questo tipo.

Se volete conoscere il tipo utilizzato all'interno del vostro metodo di portata - il tipo che dichiarati o è stato scelto dal compilatore - è possibile aggiungere un piuttosto semplice metodo di estensione:

public static Type GetCurrentType<T>(this T obj) 
{ 
    return typeof(T); 
} 

public static void Main() 
{ 
    MyBaseClass myBase = new MyBaseClass(); 
    MyDerivedClass myDerived = new MyDerivedClass(); 
    object o = myDerived; 
    MyBaseClass b = myDerived; 

    Console.WriteLine("mybase: Type is {0}", myBase.GetCurrentType()); 
    Console.WriteLine("myDerived: Type is {0}", myDerived.GetCurrentType()); 
    Console.WriteLine("object o = myDerived: Type is {0}", o.GetCurrentType()); 
    Console.WriteLine("MyBaseClass b = myDerived: Type is {0}", b.GetCurrentType()); 
} 

/* 
This code produces the following output. 
mybase: Type is ValidatorTest.MyBaseClass 
myDerived: Type is ValidatorTest.MyDerivedClass 
object o = myDerived: Type is System.Object 
MyBaseClass b = myDerived: Type is ValidatorTest.MyBaseClass 
*/ 
2

Se GetType() era virtuale, un la classe denominata HumanBeing può sovrascriverla e restituire un oggetto Type che rappresenta Robot che viene chiamato spoofing e che impedisce che questa sia una delle funzionalità principali di CLR chiamata Type Safety.

2

Anche se è vero che non è possibile sovrascrivere il metodo object.GetType(), è possibile utilizzare "nuovo" per sovraccaricarlo completamente, in tal modo spoofing un altro tipo noto. Questo è interessante, tuttavia, non ho capito come creare un'istanza dell'oggetto "Tipo" da zero, quindi l'esempio sotto fa finta di essere un altro tipo.

public class NotAString 
{ 
    private string m_RealString = string.Empty; 
    public new Type GetType() 
    { 
     return m_RealString.GetType(); 
    } 
} 

Dopo aver creato un'istanza di questo, (nuovo NotAString()). GetType(), sarà davvero restituire il tipo per una stringa.

+1

Quasi da tutto ciò che riguarda 'GetType' ha un'istanza di' object', o almeno un tipo di base che controllano o possono ragionare. Se si dispone già di un'istanza del tipo più derivato, non è necessario richiamare "GetType" su di esso. Il punto è che finché qualcuno usa 'GetType' su un' oggetto', si può essere sicuri che sia l'implementazione del sistema, non altre definizioni personalizzate. – Servy

0

Modifica Dr di Snooze answer, al fine di "creare un'istanza del 'tipo' oggetto da zero":

public class NotAString 
{ 
    public new Type GetType() 
    { 
     return typeof(string); 
    } 
}