2010-06-10 26 views
51

Si bien se trata de aprender Unity, sigo viendo el siguiente código para anular GetControllerInstance en MVC:El uso de IsAssignableFrom y "es" palabra clave en C#

if(!typeof(IController).IsAssignableFrom(controllerType)) { ... } 

esto me parece una forma bastante complicada de básicamente escribir

if(controllerType is IController) { ... } 

aprecio existen diferencias sutiles entre is y IsAssignableFrom, es decir IsAssignableFrom no incluye a las conversiones elenco, pero estoy luchando para entender la implicación de esta differenc e en escenarios prácticos.

¿Cuándo se imporantant para elegir IsAssignableFrom sobre is? ¿Qué diferencia habría en el GetControllerExample?

if (!typeof(IController).IsAssignableFrom(controllerType)) 
     throw new ArgumentException(...); 
return _container.Resolve(controllerType) as IController; 

Respuesta

80

No es lo mismo.

if(controllerType is IController) 

haría siempre se evalúan como false desde controllerType es siempre una Type, y una Type nunca es un IController.

El operador is se utiliza para comprobar si una instancia es compatible con un tipo determinado.

El método IsAssignableFrom se utiliza para comprobar si un tipo es compatible con un tipo determinado.

+0

Ah ok la diferencia es obvia ahora. ¡Debería haberlo visto! – fearofawhackplanet

+0

Así que mi conjetura es que si '' U' t' y son tipos genéricos entonces 'typeof (T) .IsAssignableFrom (typeof (T))' es lo mismo que 'nuevo T() es U'? – orad

+1

No, pero sería lo mismo que 'new U() is T'. T sería el tipo de base. Siempre me tropiezo con eso. Solo recuerdo que 'IsAssignableFrom' va en dirección opuesta al operador' is'. – Jordan

16

is palabra clave sólo es aplicable para casos mientras Type.IsAssignableFrom() sólo es aplicable para tipos.

ejemplo de is

string str = "hello world"; 
if(str is String) 
{ 
    //str instance is of type String 
} 

Nota que str es una instancia y no el tipo.

ejemplo de IsAssignableFrom()

string str = "hello world"; 
if(typeof(Object).IsAssignableFrom(str.GetType())) 
{ 
    //instances of type String can be assigned to instances of type Object. 
} 

if(typeof(Object).IsAssignableFrom(typeof(string))) 
{ 
    //instances of type String can be assigned to instances of type Object. 
} 

Tenga en cuenta que, el argumento a IsAssignableFrom() no es la instancia de cadena, que es el objeto Type que representa el tipo de cadena.

21

typeof(IController).IsAssignableFrom(controllerType) prueba una Type contra la interfaz. El operador is prueba una instancia contra la interfaz.

+2

Este comentario es el más claro para mí. – Phil

5

Una diferencia notable es también que 'es' tiene un sentido intuitivo para la herencia de pruebas o implementación de la interfaz, mientras que IsAssignableFrom hace nada pero el sentido en la cara de ella. El nombre del método Type.IsAssignableFrom es vaga y confusa cuando se aplica a pruebas de herencia o la detección de implementaciones de interfaz.La siguiente contenedor para estos fines haría mucho más intuitiva, código de aplicación puede leer:

public static bool CanBeTreatedAsType(this Type CurrentType, Type TypeToCompareWith) 
    { 
     // Always return false if either Type is null 
     if (CurrentType == null || TypeToCompareWith == null) 
      return false; 

     // Return the result of the assignability test 
     return TypeToCompareWith.IsAssignableFrom(CurrentType); 
    } 

Entonces, uno puede tener la sintaxis cliente más comprensible como:

bool CanBeTreatedAs = typeof(SimpleChildClass).CanBeTreatedAsType(typeof(SimpleClass)); 
    CanBeTreatedAs = typeof(SimpleClass).CanBeTreatedAsType(typeof(IDisposable)); 

La ventaja de este método en lugar de la La palabra clave 'es' es que se puede usar en tiempo de ejecución para probar tipos arbitrarios y desconocidos, mientras que la palabra clave 'es' (y un parámetro de tipo genérico) requiere conocimiento en tiempo de compilación de tipos específicos.

+0

No veo cómo 'IsAssignableFrom' es completamente poco intuitivo. En un sistema de tipo polimórfico, a cualquier tipo se le puede asignar un valor desde cualquiera de sus subtipos, es decir, puede hacer algo como: 'SimpleBaseClass myVar = new SimpleChildClass()'. 'IsAssignableFrom' le dice si tal asignación polimórfica sería legal, y por lo tanto si un tipo es un subtipo o igual a otro. – zstewart

Cuestiones relacionadas