2009-11-23 8 views
7

Voglio avere una funzione che restituisca "Base" se una variabile della classe Base è stata passata ad essa, "Derivata" se è stata dichiarata come Derived, ecc. Non dipende dal tipo di runtime di un valore a cui è stato assegnato.Come sapere nel codice C# che viene dichiarata una variabile con

+0

Se si utilizza la seconda soluzione di Romani, perché non usare semplicemente "typeof (T)"? –

+0

@Courtney: non è possibile scrivere 'string s = null; Console.Write (typeof (s)); ', perché s non è un nome di tipo o spazio dei nomi. Non verrà compilato. –

risposta

15

Vedere il codice seguente per esempio. La chiave è usare Generics, il metodo di estensione è stato usato solo per una bella sintassi.

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); 
    } 
} 

Risultato:

ICollection 
IEnumerable 
IList`1 
List`1 

EDIT: Si può anche evitare l'uso di metodo di estensione qui, in quanto causerebbe che appaia sul ogni IntelliSense elenco a discesa. Vedere un altro esempio:

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); 
    } 
} 

produce anche risultati corretti.

+1

+1. Liscio! (riempiendo il limite di 15 caratteri) – Heinzi

+0

Eeeek !!! molte grazie!!! – Misha

+1

Userò la seconda soluzione (dalla tua modifica), grazie – Misha

2

Basta recitare su GetType() finché non si colpisce oggetto.

+1

Sì, l'ho fatto, ha funzionato, ma lentamente. – Misha

4

Questo non è possibile senza analizzare il codice in questione.

In fase di esecuzione solo due pezzi di informazione tipo sono disponibili, l'effettiva tipo di un valore (via object.GetType()) e, se la variabile in questione è un parametro o una classe/variable esempio la proprietà FieldType sulla un FieldInfo, PropertyType su un oggetto PropertyInfo o ParameterType su un oggetto Parameter.

Poiché il valore passato a voi potrebbe essere arrivato tramite più variabili sul suo percorso, la domanda non è nemmeno ben definita, temo.

Ah - Vedo che vuoi solo il tipo come attualmente definito nel metodo, la funzionalità Espressione fornirà questo (la risposta di Roman mostra un modo pulito per farlo) ma fai attenzione a provare a usare questo al di fuori del metodo ... In Essenzialmente stai lasciando che l'inferenza di tipo generico del compilatore inferisca il tipo in questione ma questo significa che la variabile utilizzata è non sempre la variabile che puoi vedere. Può invece essere quella di una variabile compilatore sintetizzato, per esempio:

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

Poiché il compilatore sintetizza una variabile temporanea in cui inserire un riferimento oggetto x.

+0

+1, btw, effettivo è definito come "concreto" tipo ... –

+0

Non ero interessato a un valore, solo il nome di tipo la variabile è stata dichiarata con ... Grazie comunque, informazioni utili. – Misha

+0

+1 per i tuoi avvisi –

Problemi correlati