Pourquoi le mot-clé ‘this’ est-il requirejs pour appeler une méthode d’extension à partir de la classe étendue?

J’ai créé une méthode d’extension pour un ASP.NET MVC ViewPage, par exemple:

public static class ViewExtensions { public static ssortingng Method(this ViewPage page) where T : class { return "something"; } } 

Lorsque j’appelle cette méthode depuis un View (dérivée de ViewPage ), j’obtiens l’erreur ” CS0103: Le nom” Method “n’existe pas dans le contexte actuel ” sauf si j’utilise le mot this clé this pour l’appeler:

     

Pourquoi this mot this clé est- this requirejs? Ou ça marche sans ça, mais il me manque quelque chose?

(Je pense qu’il doit y avoir une copie de cette question, mais je n’ai pas pu en trouver une)

Mise à jour :

Comme le dit Ben Robinson , la syntaxe pour appeler les méthodes d’extension est simplement du sucre du compilateur. Alors pourquoi le compilateur ne peut-il pas vérifier automatiquement les méthodes d’extension des types de base du type actuel sans avoir besoin de ce mot clé?

Quelques points:

Tout d’abord, la fonctionnalité proposée (implicite “this.” Sur un appel de méthode d’extension) n’est pas nécessaire . Des méthodes d’extension étaient nécessaires pour que la compréhension des requêtes LINQ fonctionne comme nous le voulions; le destinataire est toujours indiqué dans la requête, il n’est donc pas nécessaire de prendre en charge cela implicite pour que LINQ fonctionne.

Deuxièmement, cette fonctionnalité va à l’ encontre de la conception plus générale des méthodes d’extension: à savoir que les méthodes d’extension vous permettent d’étendre un type que vous ne pouvez pas étendre , soit parce qu’il s’agit d’une interface et que vous ne le connaissez pas. connaître l’implémentation mais ne pas avoir le code source.

Si vous vous trouvez dans un scénario où vous utilisez une méthode d’extension pour un type de ce type, vous avez access au code source. Pourquoi utilisez-vous une méthode d’extension en premier lieu alors? Vous pouvez écrire une méthode d’instance vous-même si vous avez access au code source du type étendu, et vous n’avez alors plus besoin d’utiliser une méthode d’extension! Votre implémentation peut alors tirer parti de l’access à l’état privé de l’object, ce que les méthodes d’extension ne peuvent pas.

Faciliter l’utilisation des méthodes d’extension à partir d’un type auquel vous avez access encourage l’utilisation de méthodes d’extension par rapport aux méthodes d’instance. Les méthodes d’extension sont excellentes, mais il est généralement préférable d’utiliser une méthode d’instance si vous en avez une.

Compte tenu de ces deux points, il n’appartient plus au concepteur de la langue d’expliquer pourquoi la fonctionnalité n’existe pas . Il vous incombe maintenant d’expliquer pourquoi. Les fonctionnalités sont associées à des coûts énormes. Cette fonctionnalité n’est pas nécessaire et va à l’encontre des objectives de conception des méthodes d’extension. Pourquoi devrions-nous assumer le coût de sa mise en œuvre? Expliquez quel scénario important et convaincant est activé par cette fonctionnalité et nous envisagerons de l’implémenter à l’avenir. Je ne vois aucun scénario convaincant et important qui le justifie, mais il y en a peut-être un que j’ai manqué.

Sans cela, le compilateur le voit simplement comme une méthode statique dans une classe statique qui prend la page comme premier paramètre. c’est à dire

 // without 'this' ssortingng s = ViewExtensions.Method(page); 

contre.

 // with 'this' ssortingng s = page.Method(); 

Sur les méthodes d’instance, «this» est implicitement transmis à chaque méthode de manière transparente, de sorte que vous pouvez accéder à tous les membres fournis.

Les méthodes d’extension sont statiques. En appelant Method() plutôt que this.Method() ou Method(this) , vous ne dites pas au compilateur quoi transmettre à la méthode.

Vous pourriez dire «pourquoi ne se rend-il pas compte de ce qu’est l’object appelant et passe-le en paramètre?

La réponse est que les méthodes d’extension sont statiques et peuvent être appelées à partir d’un contexte statique, où il n’y a pas de «ceci».

Je suppose qu’ils pourraient vérifier cela pendant la compilation, mais pour être honnête, c’est probablement beaucoup de travail pour des gains extrêmement faibles. Et pour être honnête, je vois peu d’avantages à éliminer certaines des explications des appels de méthodes d’extension. Le fait qu’ils puissent être confondus avec des méthodes d’instance signifie qu’ils peuvent parfois être peu intuitifs (NullReferenceExceptions n’étant pas générées par exemple). Je pense parfois qu’ils auraient dû introduire un nouvel opérateur de style «pipe-forward» pour les méthodes d’extension.

Il est important de noter qu’il existe des différences entre les méthodes d’extension et les méthodes régulières. Je pense que vous venez de rencontrer l’un d’entre eux.

Je vais vous donner un exemple d’une autre différence: il est assez facile d’appeler une méthode d’extension sur une référence à un object null . Heureusement, cela est beaucoup plus difficile à faire avec des méthodes régulières. (Mais cela peut être fait. IIRC, Jon Skeet a montré comment faire en manipulant le code CIL.)

 static void ExtensionMethod(this object obj) { ... } object nullObj = null; nullObj.ExtensionMethod(); // will succeed without a NullReferenceException! 

Cela étant dit, je suis d’accord sur le fait qu’il semble peu logique que this soit nécessaire pour appeler la méthode de l’extension. Après tout, une méthode d’extension devrait idéalement “se sentir” et se comporter comme une méthode normale.

Mais, en réalité, les méthodes d’extension ressemblent plus à du sucre syntaxique qu’au langage existant, à la différence d’une caractéristique initiale qui s’intègre parfaitement au langage à tous égards.

Parce que la méthode d’extension n’existe pas avec la classe ViewPage. Vous devez indiquer au compilateur sur quoi vous appelez la méthode d’extension. Rappelez-vous que this.Method() est juste le sucre du compilateur pour ViewExtensions.Method(this) . C’est la même manière que vous ne pouvez pas appeler une méthode d’extention au milieu d’une classe par le nom de la méthode.

Je travaille sur une API fluide et j’ai rencontré le même problème. Même si j’ai access à la classe que je prolonge, je souhaitais toujours que la logique de chacune des méthodes couramment employées figure dans leurs propres fichiers. Le mot-clé “this” était très peu intuitif, les utilisateurs pensaient que la méthode manquait. J’ai fait de ma classe une classe partielle qui implémentait les méthodes dont j’avais besoin au lieu d’utiliser des méthodes d’extension. Je n’ai vu aucune mention de partiels dans les réponses. Si vous avez cette question, les partiels pourraient être une meilleure option.