Utilisation du mot clé IsAssignableFrom et «is» dans C #

En essayant d’apprendre Unity , je continue à voir le code suivant pour GetControllerInstance dans MVC:

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

cela me semble un moyen assez compliqué d’écrire essentiellement

 if(controllerType is IController) { ... } 

J’apprécie les différences subtiles entre is et IsAssignableFrom , c’est-à-dire IsAssignableFrom n’inclut pas les conversions de cast, mais j’ai du mal à comprendre l’implication de cette différence dans des scénarios pratiques.

Quand est-il important de choisir IsAssignableFrom over is ? Quelle différence cela ferait-il dans l’exemple GetControllerExample ?

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

Ce n’est pas la même chose.

 if(controllerType is IController) 

serait toujours évalué à false puisque controllerType est toujours un Type , et un Type n’est jamais un IController .

L’opérateur is permet de vérifier si une instance est compatible avec un type donné.

La méthode IsAssignableFrom permet de vérifier si un type est compatible avec un type donné.

typeof(IController).IsAssignableFrom(controllerType) teste un Type sur l’interface. L’opérateur is teste une instance sur l’interface.

is keyword n’est applicable que pour les instances alors que Type.IsAssignableFrom () ne s’applique qu’aux types.

exemple de is

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

Notez que str est une instance et non le type.

exemple de IsAssignableFrom()

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

Notez que l’argument de IsAssignableFrom () n’est pas l’instance de Ssortingng, c’est l’object Type qui représente le type de chaîne.

Une différence notable est que «is» est intuitif pour tester l’inheritance ou l’implémentation de l’interface, alors qu’IsAssignableFrom est tout sauf logique. Le nom de la méthode Type.IsAssignableFrom est vague et déroutant lorsqu’il est appliqué au test d’inheritance ou à la détection des implémentations d’interface. Le wrapper suivant à ces fins rendrait le code d’application beaucoup plus intuitif et lisible:

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

Ensuite, on peut avoir une syntaxe client plus compréhensible comme:

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

L’avantage de cette méthode au lieu du mot clé ‘is’ est qu’elle peut être utilisée au moment de l’exécution pour tester des types arbitraires inconnus, tandis que le mot clé ‘is’ (et un paramètre Type générique) requirejs une connaissance à la compilation de types spécifiques. .