2009-04-02 27 views
56

Come è possibile confrontare i tipi di due oggetti dichiarati come tipo.Confronto tipo oggetto C#

Voglio sapere se due oggetti sono dello stesso tipo o della stessa classe base.

Qualsiasi aiuto è apprezzato.

ad es.

private bool AreSame(Type a, Type b) { 

} 

risposta

84

Say a e b sono i due oggetti. Se volete vedere se a e b sono nella stessa gerarchia di ereditarietà, quindi utilizzare Type.IsAssignableFrom:

var t = a.GetType(); 
var u = b.GetType(); 

if (t.IsAssignableFrom(u) || u.IsAssignableFrom(t)) { 
    // x.IsAssignableFrom(y) returns true if: 
    // (1) x and y are the same type 
    // (2) x and y are in the same inheritance hierarchy 
    // (3) y is implemented by x 
    // (4) y is a generic type parameter and one of its constraints is x 
} 

Se si desidera verificare se uno è una classe di base dell'altro, quindi provare Type.IsSubclassOf.

Se si conosce la classe di base specifica, poi basta usare la parola chiave is:

if (a is T && b is T) { 
    // Objects are both of type T. 
} 

In caso contrario, dovrete camminare direttamente la gerarchia di ereditarietà.

+0

+1 Non ero a conoscenza di questa pratica funzione IsAssignableFrom, dovrò tenerlo a mente. – James

+0

Ci sono molte cose utili nella gerarchia di Reflection! È interessante sfogliare l'elenco dei membri: è molto probabile che troverai ciò di cui hai bisogno. Leggi i documenti, però. Ad esempio, IsAssignableFrom restituirebbe true se t era un tipo generico param e u era un vincolo. –

+0

Solo per FYI, tuttavia, questo non restituirà true se le due classi hanno la stessa classe base. –

13

È inoltre possibile utilizzare la parola chiave "IS", se si prevede che le due istanze di oggetto siano di un determinato tipo. Ciò funzionerà anche per confrontare le sottoclassi con le classi parent e anche le classi che implementano le interfacce e così via. Questo però non funzionerà con tipi di tipo.

if (objA Is string && objB Is string) 
// they are the same. 

public class a {} 

public class b : a {} 

b objb = new b(); 

if (objb Is a) 
// they are of the same via inheritance 
+0

Non so quali tipi possono essere, basta sapere se sono uguali o della stessa classe base. –

+1

Funziona solo su istanze di tipi, non su tipi di tipo Tipo. –

31

C'è un po 'di problemi con questa idea, tuttavia, dato che ogni oggetto (e, di fatto, ogni tipo) ha una classe base comune, Object. Quello che devi definire è fino a che punto della catena di successione vuoi andare (se sono o sono gli stessi o hanno lo stesso genitore immediato, o uno è il genitore diretto dell'altro, ecc.) E fai il tuo controlla in questo modo. IsAssignableFrom è utile per determinare se i tipi sono compatibili tra loro, ma non stabilirà completamente se hanno lo stesso genitore (se è quello che cerchi).

Se i criteri rigorosi è che la funzione dovrebbe restituire vero se ...

  • I tipi sono identici
  • Un tipo è il genitore (immediata o meno) degli altri
  • I due tipi hanno lo stesso padre immediato

Si potrebbe utilizzare

private bool AreSame(Type a, Type b) 
{ 
    if(a == b) return true; // Either both are null or they are the same type 

    if(a == null || b == null) return false; 

    if(a.IsSubclassOf(b) || b.IsSubclassOf(a)) return true; // One inherits from the other 

    return a.BaseType == b.BaseType; // They have the same immediate parent 
} 
+0

ottimo campione e spiegazione. +1 –

+0

Desideravo che ci fosse un modo per condividere una risposta accettata. Di nuovo. –

+0

@Adam: Mi chiedo se non c'è un modo per combinare entrambi i nostri approcci. È possibile mantenere un elenco di tipi risultanti dal prendere BaseType.GetType() su entrambi i punti a e b fino a che (1) non si raggiunge System.Object (o qualche altro tipo derivato limitato) [fail] o (2) c'è una corrispondenza [ passaggio]. –

2

Ho provato quanto segue con una gerarchia utilizzando sia le interfacce che le classi concrete. Apre la catena della classe base per uno dei tipi fino a raggiungere "oggetto" in corrispondenza del quale controlliamo se il tipo di destinazione corrente è assegnabile al tipo di origine. Controlliamo anche se i tipi hanno un'interfaccia comune. se lo fanno allora sono 'AreSame'

Spero che questo aiuti.

public interface IUser 
{ 
    int ID { get; set; } 
    string Name { get; set; } 
} 

public class NetworkUser : IUser 
{ 
    public int ID 
    { 
     get; 
     set; 
    } 

    public string Name 
    { 
     get; 
     set; 
    } 
} 

public class Associate : NetworkUser,IUser 
{ 
    #region IUser Members 

    public int ID 
    { 
     get; 
     set; 
    } 

    public string Name 
    { 
     get; 
     set; 
    } 

    #endregion 
} 

public class Manager : NetworkUser,IUser 
{ 
    #region IUser Members 

    public int ID 
    { 
     get; 
     set; 
    } 

    public string Name 
    { 
     get; 
     set; 
    } 

    #endregion 
} 


public class Program 
{ 

    public static bool AreSame(Type sourceType, Type destinationType) 
    { 
     if (sourceType == null || destinationType == null) 
     { 
      return false; 
     } 

     if (sourceType == destinationType) 
     { 
      return true; 
     } 

     //walk up the inheritance chain till we reach 'object' at which point check if 
    //the current destination type is assignable from the source type  
    Type tempDestinationType = destinationType; 
     while (tempDestinationType.BaseType != typeof(object)) 
     { 
      tempDestinationType = tempDestinationType.BaseType; 
     } 
     if(tempDestinationType.IsAssignableFrom(sourceType)) 
     { 
      return true; 
     } 

     var query = from d in destinationType.GetInterfaces() join s in sourceType.GetInterfaces() 
        on d.Name equals s.Name 
        select s; 
     //if the results of the query are not empty then we have a common interface , so return true 
    if (query != Enumerable.Empty<Type>()) 
     { 
      return true; 
     } 
     return false;    
    } 

    public static void Main(string[] args) 
    { 

     AreSame(new Manager().GetType(), new Associate().GetType()); 
    } 
} 
+0

thx per il codice. +1 –