2009-04-02 17 views
56

¿Cómo puedo comparar los tipos de dos objetos declarados como tipo?C# Comparación del tipo de objeto

Quiero saber si dos objetos son del mismo tipo o de la misma clase base.

Cualquier ayuda es apreciada.

p. Ej.

private bool AreSame(Type a, Type b) { 

} 

Respuesta

84

Say a y b son los dos objetos. Si desea ver si a y b están en la misma jerarquía de herencia, a continuación, utilizar 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 desea comprobar si se trata de una clase base de la otra, y luego tratar Type.IsSubclassOf.

Si conoce la clase base específica, a continuación, sólo tiene que utilizar la palabra clave is:

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

De lo contrario, tendrá que caminar por la jerarquía de herencia directa.

+0

+1 No conocía esa práctica función IsAssignableFrom, tendré que tener eso en cuenta. – James

+0

¡Hay muchas cosas útiles en la jerarquía Reflexión! Es interesante simplemente navegar por la lista de miembros; es muy probable que encuentres lo que necesitas. Sin embargo, lea los documentos. Por ejemplo, IsAssignableFrom devolvería true si t fuera un tipo genérico param y u fuera una restricción. –

+0

Solo para su información, esto no será verdadero si las dos clases tienen la misma clase base. –

13

También puede utilizar la palabra clave "IS", si espera que las dos instancias de objeto sean de un cierto tipo. Esto también funcionará para comparar subclases con clases principales y también clases que implementan interfaces, etc. Esto no funcionará para los tipos de tipo Tipo sin embargo.

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

No sé qué tipos pueden ser, solo necesita saber si son los mismos o de la misma clase base. –

+1

Esto solo funciona en instancias de tipos, no para tipos de tipo Tipo. –

31

Sin embargo, hay un pequeño problema con esta idea, ya que cada objeto (y, de hecho, cada tipo) tiene una clase base común, Object. Lo que necesita definir es qué tan lejos en la cadena de herencia desea ir (si son los mismos o si tienen el mismo padre inmediato, o uno es el padre inmediato del otro, etc.) y hacen su comprueba de esa manera. IsAssignableFrom es útil para determinar si los tipos son compatibles entre sí, pero no establecerá completamente si tienen el mismo elemento principal (si eso es lo que busca).

Si sus criterios estrictos es que la función debe devolver verdadero si ...

  • Los tipos son idénticos
  • Un tipo es el padre (inmediata o de otra manera) de la otra
  • Los dos tipos tienen el mismo padre inmediato

Usted podría utilizar

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

gran muestra y explicación. +1 –

+0

Ojalá hubiera una forma de compartir una respuesta aceptada. Thx otra vez. –

+0

@Adam: Me pregunto si no hay una forma de combinar ambos enfoques. Podría mantener una lista de tipos que resultaron de tomar BaseType.GetType() en ayb hasta que (1) haya alcanzado System.Object (o algún tipo derivado más restringido) [fail] o (2) haya una coincidencia [ pasar]. –

2

Probé lo siguiente con una jerarquía utilizando interfaces y clases concretas. Sube la cadena de la clase base para uno de los tipos hasta que llega al "objeto" en el que comprobamos si el tipo de destino actual se puede asignar al tipo de fuente. También verificamos si los tipos tienen una interfaz común. si lo hacen, entonces 'AreSame'

Espero que esto ayude.

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 para el código. +1 –