144 votes

Pourquoi GetType() ne trouve-t-il pas les types lorsqu'il est invoqué par un délégué de groupe de méthodes ?

Nous avons un programme très simple qui invoque le Type.GetType méthode statique. Les deux exemples devraient retourner une instance de type valide. Seul le second l'est réellement. Il semble que quelque chose de bizarre se passe avec la pile de crawl utilisée par GetType mais quel est exactement le problème ici ? Est-ce un bug ou une fonctionnalité obscure ?

public class TestClass { }

class Program
{
    static void Main(string[] args)
    {
        var fullName = typeof(TestClass).FullName;
        Console.WriteLine("Full name: {0}", fullName);

        new[] { fullName }.Select(Type.GetType).ToList().ForEach(t => Console.WriteLine("Method group: '{0}'", t));
        new[] { fullName }.Select(t => Type.GetType(t)).ToList().ForEach(t => Console.WriteLine("Closure: '{0}'", t));
    }
}

En cours d'exécution :

Full name: GetTypeBeingWeird.TestClass
Method group: ''
Closure: 'GetTypeBeingWeird.TestClass'

165voto

Jon Skeet Points 692016

C'est vraiment intéressant. C'est un mélange du comportement de Type.GetType(string) en termes d'assemblage appelant, et comment les conversions de groupes de méthodes fonctionnent.

Tout d'abord, le Type.GetType La documentation inclut ceci :

Si Nom du type inclut l'espace de noms mais pas le nom de l'assemblage, cette méthode ne recherche que l'assemblage de l'objet appelant et Mscorlib.dll, dans cet ordre.

Dans votre premier appel, vous passez dans un délégué qui appelle Type.GetType ... mais il n'est pas particulièrement appelé depuis votre assemblée. Il est effectivement appelé directement de la Select dans LINQ... si vous regardez la trace de la pile à partir de l'intérieur de Type.GetType vous verrez Select comme l'appelant direct, je crois.

Dans votre deuxième appel, vous passez dans une fermeture qui appelle Type.GetType et cet appel se trouve dans votre assemblée.

C'est pourquoi il trouve le type dans le second cas mais pas dans le premier. Ceci est encore validé en spécifiant un type qui se trouve dans l'assemblage LINQ :

var fullName = typeof(Enumerable).FullName;

Les résultats sont alors inversés :

Full name: System.Linq.Enumerable
Method group: 'System.Linq.Enumerable'
Closure: ''

Si vous spécifiez quelque chose dans mscorlib (par ex. typeof(string).FullName ), les deux approches fonctionnent :

Full name: System.String
Method group: 'System.String'
Closure: 'System.String'

La façon de contourner cette bizarrerie lors de la recherche de votre classe, en utilisant toujours un groupe de méthodes, est simplement de fournir le nom qualifié d'assemblage à la place :

var fullName = typeof(TestClass).AssemblyQualifiedName;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X