2009-11-23 6 views
7

Je veux avoir une fonction qui retournerait "Base" si une variable de classe Base lui était passée, "Dérivée" si elle était déclarée comme Derived, etc Non selon le type d'exécution d'une valeur à laquelle il a été affecté.Comment savoir en C# code avec lequel une variable a été déclarée avec

+0

Si vous utilisez la deuxième solution de Romans, pourquoi ne pas simplement utiliser 'typeof (T)'? –

+0

@Courtney: Vous ne pouvez pas écrire 'string s = null; Console.Write (typeof (s)); ', car s n'est pas un nom de type ou d'espace de nom. Il ne compilera pas. –

Répondre

15

Voir le code ci-dessous par exemple. La clé est d'utiliser Generics, la méthode d'extension a été utilisée juste pour la syntaxe sympa.

using System; 

static class Program 
{ 
    public static Type GetDeclaredType<T>(this T obj) 
    { 
     return typeof(T); 
    } 

    // Demonstrate how GetDeclaredType works 
    static void Main(string[] args) 
    { 
     ICollection iCollection = new List<string>(); 
     IEnumerable iEnumerable = new List<string>(); 
     IList<string> iList = new List<string>(); 
     List<string> list = null; 

     Type[] types = new Type[]{ 
      iCollection.GetDeclaredType(), 
      iEnumerable.GetDeclaredType(), 
      iList.GetDeclaredType(), 
      list.GetDeclaredType() 
     }; 

     foreach (Type t in types) 
      Console.WriteLine(t.Name); 
    } 
} 

Résultat:

ICollection 
IEnumerable 
IList`1 
List`1 

EDIT: Vous pouvez également éviter d'utiliser la méthode d'extension ici, car il fait paraître sur chaque IntelliSense liste déroulante. Voir un autre exemple:

using System; 
using System.Collections; 

static class Program 
{ 
    public static Type GetDeclaredType<T>(T obj) 
    { 
     return typeof(T); 
    } 

    static void Main(string[] args) 
    { 
     ICollection iCollection = new List<string>(); 
     IEnumerable iEnumerable = new List<string>(); 

     Type[] types = new Type[]{ 
       GetDeclaredType(iCollection), 
       GetDeclaredType(iEnumerable) 
     }; 

     foreach (Type t in types) 
      Console.WriteLine(t.Name); 
    } 
} 

produit également des résultats corrects.

+1

+1. Lisse! (remplissage pour la limite de 15 char) – Heinzi

+0

wow! Merci beaucoup!!! – Misha

+1

Je vais utiliser la 2ème solution (de votre édition), merci – Misha

2

Recurve juste sur GetType() jusqu'à ce que vous atteigniez l'objet.

+1

Oui, je l'ai fait, ça a marché mais lentement. – Misha

4

Ceci n'est pas possible sans analyser le code en question.

Lors de l'exécution seulement deux informations de type sont disponibles, la réelle type d'une valeur (via object.GetType()) et, si la variable en question est un paramètre ou une classe/variable d'instance la propriété sur FieldType un FieldInfo, PropertyType sur un PropertyInfo ou ParameterType sur un ParameterInfo.

Étant donné que la valeur qui vous a été transmise pourrait bien provenir de plusieurs variables sur son chemin vers vous, la question n'est même pas bien définie, j'en ai peur. Ah - Je vois que vous ne voulez que le type actuellement défini dans la méthode, la fonctionnalité Expression vous le fournira (la réponse de Roman montre une bonne façon de le faire) mais méfiez-vous d'essayer de l'utiliser en dehors de la méthode ... essence vous laissez l'inférence de type générique du compilateur inférer le type en question mais cela signifie que la variable utilisée est pas toujours la variable que vous pouvez voir. Il peut au contraire être celle d'une variable synthétisée du compilateur, par exemple:

string x = "x"; 
Console.WriteLine(x.GetDeclaredType()); // string 
Console.WriteLine(((object)x).GetDeclaredType()); // object 

Depuis le compilateur synthétisant une variable temporaire dans lequel placer une référence d'objet à x.

+0

+1, btw, réel est appelé type "béton" ... –

+0

Je n'étais pas intéressé par une valeur, seul le nom du type de la variable a été déclaré avec ... Merci quand même, informations utiles. – Misha

+0

+1 pour vos avertissements –

Questions connexes