2009-04-02 6 views
56

Comment puis-je comparer les types de deux objets déclarés comme type.C# Type de comparaison d'objet

Je veux savoir si deux objets sont du même type ou de la même classe de base.

Toute aide est appréciée.

par exemple.

private bool AreSame(Type a, Type b) { 

} 

Répondre

84

Say a et b sont les deux objets. Si vous voulez voir si a et b sont dans la même hiérarchie d'héritage, puis utilisez 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 
} 

Si vous voulez vérifier si l'on est une classe de base de l'autre, essayez Type.IsSubclassOf.

Si vous connaissez la classe de base spécifique, il suffit d'utiliser le mot-clé is:

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

Sinon, vous devrez marcher la hiérarchie d'héritage directement.

+0

+1 Je n'étais pas au courant de cette fonction pratique IsAssignableFrom, je vais devoir garder cela à l'esprit. – James

+0

Il y a pas mal de choses utiles dans la hiérarchie de Reflection! Il est intéressant de simplement parcourir la liste des membres - les chances sont assez bonnes, vous trouverez ce dont vous avez besoin. Lisez les documents, cependant. Par exemple, IsAssignableFrom renverrait true si t était un param de type générique et que u était une contrainte. –

+0

Juste pour info, cela ne retournera pas vrai si les deux classes ont la même classe de base. –

13

Vous pouvez également utiliser le « IS » mot-clé, si vous vous attendez les deux instances d'objet à un certain type. Cela fonctionnera également pour comparer des sous-classes à des classes parentes et aussi des classes qui implémentent des interfaces et ainsi de suite. Cela ne fonctionnera pas pour les types de type Type.

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

Je ne sais pas quels types ils peuvent être, juste besoin de savoir s'ils sont identiques ou de la même classe de base. –

+1

Cela fonctionne uniquement sur les instances de types, pas pour les types de type Type. –

31

Il y a un petit problème avec cette idée, car chaque objet (et, en fait, chaque type) a une classe de base commune, Object. Ce que vous devez définir, c'est jusqu'où vous voulez aller dans la chaîne d'héritage (que ce soit la même chose ou le même parent immédiat, ou l'un est le parent immédiat de l'autre, etc.) et faites votre vérifie de cette façon. IsAssignableFrom est utile pour déterminer si les types sont compatibles les uns avec les autres, mais n'établira pas complètement s'ils ont le même parent (si c'est ce que vous recherchez).

Si vos critères stricts est que la fonction doit retourner vrai si ...

  • Les types sont identiques
  • Un type est le parent (immédiat ou autre) de l'autre
  • Les deux types ont le même parent immédiat

Vous pouvez utiliser

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

super échantillon et explication. +1 –

+0

J'aurais aimé qu'il y ait un moyen de partager une réponse acceptée. Thx à nouveau. –

+0

@Adam: Je me demande s'il n'y a pas moyen de combiner nos deux approches. Vous pouvez conserver une liste des types résultant de la prise de BaseType.GetType() sur a et b jusqu'à ce que vous (1) atteigniez System.Object (ou un type dérivé plus restreint) [fail] ou (2) il y a une correspondance [ passer]. –

2

J'ai essayé ce qui suit avec une hiérarchie en utilisant à la fois des interfaces et des classes concrètes. Il parcourt la chaîne de classes de base pour l'un des types jusqu'à ce qu'il atteigne "objet" à laquelle nous vérifions si le type de destination actuel est assignable au type de source. Nous vérifions également si les types ont une interface commune. s'ils le font alors ils sont 'AreSame'

Espérons que cela aide.

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 pour le code. +1 –