C #, implémenter des méthodes de type ‘abstrait statique’

J’ai récemment rencontré un problème où il me semble que j’ai besoin d’une méthode «statique abstraite». Je sais pourquoi c’est impossible, mais comment puis-je contourner cette limitation?

Par exemple, j’ai une classe abstraite qui a une chaîne de description. Comme cette chaîne est commune à toutes les instances, elle est marquée comme statique, mais je souhaite que toutes les classes dérivées de cette classe fournissent leur propre propriété Description. Je l’ai donc marquée comme étant abstraite:

abstract class AbstractBase { ... public static abstract ssortingng Description{get;} ... } 

Cela ne comstack pas bien sûr. J’ai pensé à utiliser des interfaces mais les interfaces peuvent ne pas contenir de signatures de méthodes statiques.

Dois-je le rendre simplement non statique, et toujours obtenir une instance pour obtenir cette information spécifique à la classe?

Des idées?

Combiner statique et abstrait n’a aucun sens, oui. L’idée derrière le statique est qu’il n’est pas nécessaire de présenter une instance de la classe pour utiliser le membre en question; Cependant, avec abstract, on s’attend à ce qu’une instance soit d’une classe dérivée qui fournit une implémentation concrète.

Je peux voir pourquoi vous voudriez ce genre de combinaison, mais le fait est que le seul effet serait de refuser l’utilisation de l’implémentation de ‘this’ ou de tout membre non statique. C’est-à-dire que la classe parente dicterait une ressortingction dans l’implémentation de la classe dérivée, même s’il n’y a pas de différence sous-jacente entre l’appel d’un membre abstrait ou “statique abstrait”

Vous ne pouvez pas

Le lieu pour cela est avec les atsortingbuts.

Par exemple

 [Name("FooClass")] class Foo { } 

Si cela ne vous dérange pas de repousser les implémentations pour implémenter judicieusement la propriété Description, vous pouvez simplement faire

 public abstract ssortingng ClassDescription {get; } // ClassDescription is more intention-revealing than Description 

Et les classes d’implémentation feraient quelque chose comme ceci:

 static ssortingng classDescription="My Description for this class"; override ssortingng ClassDescription { get { return classDescription; } } 

Ensuite, vos classes doivent suivre le contrat de description, mais vous leur laissez le soin de le faire de manière judicieuse. Il n’y a aucun moyen de spécifier une implémentation de manière orientée object (sauf à travers des hacks cruels et fragiles).

Cependant, dans mon esprit, cette description est constituée de métadonnées de classe, alors je préférerais utiliser le mécanisme d’atsortingbut comme d’autres l’ont décrit. Si vous êtes particulièrement préoccupé par les multiples utilisations de la reflection, créez un object qui reflète l’atsortingbut concerné et stockez un dictionnaire entre le Type et la Description. Cela minimisera la reflection (autre que l’inspection du type à l’exécution, ce qui n’est pas si grave). Le dictionnaire peut être stocké en tant que membre de la classe qui a généralement besoin de ces informations ou, si les clients le requièrent, via un object singleton ou contextuel.

Si c’est statique, il n’y a qu’une seule instance de la variable, je ne vois pas comment l’inheritance aurait du sens si nous pouvions faire ce que vous voulez accomplir avec des vars statiques dans les classes dérivées. Personnellement, je pense que vous allez trop loin pour essayer d’éviter une instance var.

Pourquoi pas la manière classique?

 abstract class AbstractBase { protected ssortingng _Description = "I am boring abstract default value"; } class Foo : AbstractBase { public Foo() { _Description = "I am foo!"; } } 

Ce n’est pas statique s’il doit être appelé sur une instance.

Si vous ne l’appelez pas sur une instance, il n’y a pas de polymorphism en jeu (c.-à-d. Que ChildA.Description n’a rien à voir avec ChildB.Description en ce qui concerne le langage).

Une solution possible consiste à définir un singleton de votre classe dérivée dans votre classe de base à l’aide de Generics.

 import System; public abstract class AbstractBase where T : AbstractBase, new() { private static T _instance = new T(); public abstract ssortingng Description { get; } public static ssortingng GetDescription() { return _instance.Description; } } public class DerivedClass : AbstractBase { public override ssortingng Description => "This is the derived Class"; } class Program { static void Main(ssortingng[] args) { Console.WriteLine(DerivedClass.GetDescription()); Console.ReadKey(); } } 

L’astuce consiste à dire à votre AbstractBase quelques détails sur la manière dont DerivedClass est implémenté:

  • Il est utilisable avec where T: new() pour créer une instance Singleton
  • Il dérive de lui-même avec where T : AbstractBase donc il sait qu’il y aura une implémentation de Description

De cette façon, _instance contient le champ Description qui peut être appelé dans la méthode statique GetDescription() . Cela vous oblige à remplacer Description dans votre DerivedClass et vous permet d’appeler sa valeur avec DerivedClass.GetDescription()

Vous pouvez faire en sorte que la méthode de base “abstract” lance une Exception , donc un développeur est “averti” s’il essaie d’appeler cette méthode sur une classe enfant sans surcharger.

L’inconvénient est que l’on pourrait étendre la classe et ne pas utiliser cette méthode. Ensuite, reportez-vous aux autres réponses fournies.