2010-10-02 9 views
2

Impossible d'expliquer ce qui se passe dans le programme suivant. GetType retourne le type que je veux retourner et non l'original. Cela signifie-t-il que nous ne pouvons pas compter sur GetType? l'opérateur a raison cependant. Quelqu'un peut-il l'expliquer en détail?GetType renvoie des informations différentes de celles utilisées par l'opérateur

using System; 

namespace ConsoleApplication2 
{ 
    public class MyClass 
    { 
     public Type GetType() 
     { 
      return typeof(Program); 
     } 

    } 

class Program 
{ 
    static void Main(string[] args) 
    { 
     MyClass mc = new MyClass(); 

     if (mc.GetType() == typeof(Program)) 
     { 
      Console.WriteLine("Confused."); 
     } 
     if(mc is Program) 
     { 
      Console.WriteLine(mc.GetType()); // Don't get inside the if. Why? 
     } 

    } 
} 
} 

Mise à jour: Je lis le CLR livre via C# 3e édition. Dans le chapitre 4 (2ème page) quand il explique les méthodes différentes System.Object il dit

« La méthode GetType est nonvirtual, qui empêche une classe redéfinissant cette méthode et mentir sur son type »

Alors que je suis d'accord sur la première déclaration, je mens sur le type MyClass. n'est-ce pas?

+0

Pouvez-vous confirmer que la confusion est que mc.GetType() == typeof (Program) évalue réellement à vrai? –

+0

Oui. En fait, il semble que l'opérateur utilise un mécanisme différent pour vérifier le type que GetType(). Si oui, quel est le mécanisme? Aussi le programme ci-dessus montre que nous ne pouvons pas faire confiance à GetType pour renvoyer le type correct. – Tanmoy

+2

Je pense que vous êtes confus à propos de la différence entre la création d'une méthode ** new ** (masquer une méthode ancêtre) et ** overriding ** d'une méthode ancêtre. Eric Lippert a récemment eu [un article de blog] (http://blogs.msdn.com/b/ericlippert/archive/2010/03/29/putting-a-base-in-the-middle.aspx) qui touche à cette (il y en a probablement d'autres, mais c'est le premier que j'ai pu trouver). La lecture pourrait vous aider à comprendre ce qui se passe ici. –

Répondre

4

is operator implemented in terms of as operator et enfin d'utiliser l'instruction isinst IL. Et bien sûr, cette instruction ne connaît pas votre méthode GetType virtuelle que vous définissez dans une classe de votre hiérarchie d'héritage.

Pour comprendre ce comportement « confusion » permet de « mettre en œuvre » notre propre version du « opérateur est »:

public class MyClass 
{ 
    public Type GetType() 
    { 
     return typeof(Program); 
    } 

} 

class Program { 

    //this is oversimplified implementation, 
    //but I want to show the main differences 
    public static bool IsInstOf(object o, Type t) 
    { 
     //calling GetType on System.Object 
     return o.GetType().IsAssignableFrom(t); 
    } 

    static void Main(string[] args) 
    { 
     MyClass mc = new MyClass(); 

     //calling MyClass non-virtual version for GetType method 
     if (mc.GetType() == typeof(Program)) 
     { 
      //Yep, this condition is true 
      Console.WriteLine("Not surprised!"); 
     } 

     //Calling System.Object non-virtual version for GetType method 
     if (IsInstOf(mc, typeof(Program))) 
     { 
      //Nope, this condition isn't met! 
      //because mc.GetType() != ((object)mc).GetType()! 
     } 

     Console.ReadLine(); 
    }    
} 
0

il ne sera vrai si:

if (mc is MyClass) { ... } 
1

est vérifie le type d'exécution réelle de votre variable. Le compilateur ne se soucie pas que vous avez défini une méthode appelée GetType() qui renvoie une autre Type. Il sait toujours que le type actuall de votre variable est MyClass.

Qu'est-ce que vous essayez exactement d'accomplir ici? Pourquoi avez-vous besoin de votre classe MyClass pour emprunter l'identité de la classe Program?

3

Object.GetType n'est pas une méthode virtuelle. Donc mc is MyClass et appelle effectivement Object.GetType et non votre méthode.

+0

Comment ça (l'opérateur) le fait-il? Est-ce qu'il lance d'abord mc à l'objet, puis appelle la méthode GetType? Aussi s'il vous plaît voir la mise à jour de ma question. Est-ce que les hommes alors que nous pouvons compter sur 'est' nous ne pouvons pas sur GetType directement. – Tanmoy

+3

Je crois que l'opérateur 'is' se résume à l'instruction' isinst' dans le CLR. Je ne sais pas comment cela est implémenté, mais il consulte probablement la table de l'objet similaire à GetType. Le résultat est le même que le test avec '((objet) mc) .GetType()'. – ars

4

Veuillez prendre soin de l'avertissement, tel qu'il existe pour des raisons. Votre code compilé avec l'avertissement suivant:

Warning 1 'ConsoleApplication2.MyClass.GetType()' hides inherited member 'object.GetType()'. Use the new keyword if hiding was intended.

qui signifie GetType() est la méthode non virtuelle et vous écrivez sans rapport avec des nouvelles GetType() que CLR ne sera jamais l'appeler.

+0

Je suis désolé si ma question n'a pas été claire. Son intérêt académique/théorique plutôt que d'écrire un code de production avec les meilleures pratiques. – Tanmoy