Je suis fan des méthodes d'extension en C #, mais je n'ai pas réussi à ajouter une méthode d'extension à une classe statique, telle que Console.
Par exemple, si je veux ajouter une extension à la console, appelée 'WriteBlueLine', pour pouvoir aller:
Console.WriteBlueLine("This text is blue");
J'ai essayé cela en ajoutant une méthode statique publique locale, avec la console comme paramètre 'this' ... mais pas de dés!
public static class Helpers {
public static void WriteBlueLine(this Console c, string text)
{
Console.ForegroundColor = ConsoleColor.Blue;
Console.WriteLine(text);
Console.ResetColor();
}
}
Cela n'a pas ajouté de méthode 'WriteBlueLine' à la console ... est-ce que je me trompe? Ou demander l'impossible?
c#
static
extension-methods
Leon Bambrick
la source
la source
Helpers.WriteBlueLine(null, "Hi");
:)Réponses:
Les méthodes d'extension nécessitent une variable d'instance (valeur) pour un objet. Vous pouvez cependant écrire un wrapper statique autour de l'
ConfigurationManager
interface. Si vous implémentez l'encapsuleur, vous n'avez pas besoin d'une méthode d'extension car vous pouvez simplement ajouter la méthode directement.la source
Pouvez-vous ajouter des extensions statiques aux classes en C #? Non mais vous pouvez le faire:
Voici comment ça fonctionne. Bien que vous ne puissiez techniquement pas écrire de méthodes d'extension statiques, ce code exploite plutôt une faille dans les méthodes d'extension. Cette lacune étant que vous pouvez appeler des méthodes d'extension sur des objets null sans obtenir l'exception null (sauf si vous accédez à quoi que ce soit via @this).
Alors, voici comment vous utiliseriez ceci:
Maintenant, POURQUOI ai-je choisi d'appeler le constructeur par défaut à titre d'exemple, et pourquoi ne retourne-je pas simplement T () dans le premier extrait de code sans faire toutes ces ordures d'expression? Eh bien aujourd'hui, votre jour de chance car vous obtenez un 2fer. Comme tout développeur .NET avancé le sait, le nouveau T () est lent car il génère un appel à System.Activator qui utilise la réflexion pour obtenir le constructeur par défaut avant de l'appeler. Merde, Microsoft! Cependant, mon code appelle directement le constructeur par défaut de l'objet.
Les extensions statiques seraient mieux que cela, mais les temps désespérés appellent des mesures désespérées.
la source
XConsole
,ConsoleHelper
etc.(null as DataSet).Create();
pourrait êtredefault(DataSet).Create();
.Ce n'est pas possible.
Et oui, je pense que MS a fait une erreur ici.
Leur décision n'a pas de sens et oblige les programmeurs à écrire (comme décrit ci-dessus) une classe wrapper inutile.
Voici un bon exemple: Essayer d'étendre la classe de test MS Unit statique Assert: Je veux 1 méthode Assert de plus
AreEqual(x1,x2)
.La seule façon de le faire est de pointer vers différentes classes ou d'écrire un wrapper autour de 100s de différentes méthodes Assert. Pourquoi!?
Si la décision a été prise d'autoriser les extensions d'instances, je ne vois aucune raison logique de ne pas autoriser les extensions statiques. Les arguments concernant la sectionnement des bibliothèques ne tiennent pas une fois que les instances peuvent être étendues.
la source
Assert.Throws
à la réponse stackoverflow.com/questions/113395/…Je suis tombé sur ce fil tout en essayant de trouver une réponse à la même question que l'OP avait. Je n'ai pas trouvé la réponse que je voulais mais j'ai fini par le faire.
Et je l'utilise comme ceci:
la source
Vous pourriez peut-être ajouter une classe statique avec votre espace de noms personnalisé et le même nom de classe:
la source
À partir de C # 7, cela n'est pas pris en charge. Il y a cependant des discussions sur l'intégration de quelque chose comme ça dans C # 8 et des propositions qui méritent d'être soutenues .
la source
Nan. Les définitions de méthode d'extension nécessitent une instance du type que vous étendez. C'est regrettable; Je ne sais pas pourquoi c'est nécessaire ...
la source
Quant aux méthodes d'extension, les méthodes d'extension elles-mêmes sont statiques; mais elles sont invoquées comme s'il s'agissait de méthodes d'instance. Puisqu'une classe statique n'est pas instanciable, vous n'auriez jamais d'instance de la classe à partir de laquelle appeler une méthode d'extension. Pour cette raison, le compilateur ne permet pas de définir des méthodes d'extension pour les classes statiques.
M. Obnoxious a écrit: "Comme tout développeur .NET avancé le sait, le nouveau T () est lent car il génère un appel à System.Activator qui utilise la réflexion pour obtenir le constructeur par défaut avant de l'appeler".
New () est compilé dans l'instruction IL "newobj" si le type est connu au moment de la compilation. Newobj prend un constructeur pour une invocation directe. Les appels à System.Activator.CreateInstance () sont compilés dans l'instruction IL "call" pour appeler System.Activator.CreateInstance (). New () lorsqu'il est utilisé contre des types génériques entraînera un appel à System.Activator.CreateInstance (). Le message de M. Obnoxious n'était pas clair sur ce point ... et bien, désagréable.
Ce code:
produit cet IL:
la source
Vous ne pouvez pas ajouter d' électricité statique méthodes à un type. Vous pouvez uniquement ajouter des méthodes (pseudo-) d'instance à une instance d'un type.
Le but du
this
modificateur est de dire au compilateur C # de passer l'instance sur le côté gauche de la.
comme premier paramètre de la méthode statique / d'extension.Dans le cas de l'ajout de méthodes statiques à un type, il n'y a aucune instance à passer pour le premier paramètre.
la source
J'ai essayé de le faire avec System.Environment lorsque j'apprenais les méthodes d'extension et que je n'ai pas réussi. La raison est, comme d'autres le mentionnent, car les méthodes d'extension nécessitent une instance de la classe.
la source
Il n'est pas possible d'écrire une méthode d'extension, mais il est possible d'imiter le comportement que vous demandez.
Cela vous permettra d'appeler Console.WriteBlueLine (fooText) dans d'autres classes. Si les autres classes veulent accéder aux autres fonctions statiques de la console, elles devront être explicitement référencées via leur espace de noms.
Vous pouvez toujours ajouter toutes les méthodes dans la classe de remplacement si vous souhaitez les avoir toutes au même endroit.
Vous auriez donc quelque chose comme
Cela fournirait le type de comportement que vous recherchez.
* Remarque La console devra être ajoutée via l'espace de noms dans lequel vous l'avez placée.
la source
oui, dans un sens limité.
Cela fonctionne mais pas la console car elle est statique.
Cela fonctionne car tant qu'il n'est pas sur le même espace de noms. Le problème est que vous devez écrire une méthode statique proxy pour chaque méthode que System.Console possède. Ce n'est pas nécessairement une mauvaise chose car vous pouvez ajouter quelque chose comme ceci:
ou
La façon dont cela fonctionne est que vous connectez quelque chose à la ligne d'écriture standard. Il peut s'agir d'un nombre de lignes ou d'un mauvais filtre de mots ou autre. Chaque fois que vous spécifiez simplement Console dans votre espace de noms, dites WebProject1 et importez le système d'espace de noms, WebProject1.Console sera choisi par défaut sur System.Console pour ces classes dans l'espace de noms WebProject1. Ainsi, ce code transformera tous les appels Console.WriteLine en bleu dans la mesure où vous n'avez jamais spécifié System.Console.WriteLine.
la source
Ce qui suit a été rejeté comme une modification de la réponse de tvanfosson. On m'a demandé de contribuer comme ma propre réponse. J'ai utilisé sa suggestion et terminé la mise en œuvre d'un
ConfigurationManager
wrapper. En principe, j'ai simplement rempli la...
réponse de tvanfosson.la source
Vous pouvez utiliser un cast sur null pour le faire fonctionner.
L'extension:
Ton type:
la source
Vous POUVEZ le faire si vous êtes prêt à "frigorifier" un peu en créant une variable de la classe statique et en l'assignant à null. Cependant, cette méthode ne serait pas disponible pour les appels statiques sur la classe, donc vous ne savez pas combien elle serait utile:
la source