.net - Pourquoi ne puis-je pas avoir de méthodes statiques abstraites en C #?

Translate

J'ai travaillé avecfournisseursun peu ces derniers temps, et je suis tombé sur une situation intéressante où je voulais avoir une classe abstraite qui avait une méthode statique abstraite. J'ai lu quelques articles sur le sujet, et cela avait du sens, mais y a-t-il une bonne explication claire?

This question and all comments follow the "Attribution Required."

Toutes les réponses

Translate

Les méthodes statiques ne sont pasinstanciéen tant que tels, ils sont simplement disponibles sans référence d'objet.

Un appel à une méthode statique se fait via le nom de la classe, pas via une référence d'objet, et le code IL (Intermediate Language) pour l'appeler appellera la méthode abstraite via le nom de la classe qui l'a définie, pas nécessairement le nom de la classe que vous avez utilisée.

Laissez-moi vous montrer un exemple.

Avec le code suivant:

public class A
{
    public static void Test()
    {
    }
}

public class B : A
{
}

Si vous appelez B.Test, comme ceci:

class Program
{
    static void Main(string[] args)
    {
        B.Test();
    }
}

Ensuite, le code réel à l'intérieur de la méthode Main est le suivant:

.entrypoint
.maxstack 8
L0000: nop 
L0001: call void ConsoleApplication1.A::Test()
L0006: nop 
L0007: ret 

Comme vous pouvez le voir, l'appel est fait à A.Test, car c'est la classe A qui l'a défini, et non à B.Test, même si vous pouvez écrire le code de cette façon.

Si tu avaistypes de classe, comme dans Delphi, où vous pouvez faire une variable faisant référence à un type et non à un objet, vous auriez plus d'utilité pour les méthodes statiques virtuelles et donc abstraites (et aussi les constructeurs), mais elles ne sont pas disponibles et donc les appels statiques ne sont pas -virtuel dans .NET.

Je me rends compte que les concepteurs d'IL pourraient permettre au code d'être compilé pour appeler B.Test, et résoudre l'appel au moment de l'exécution, mais ce ne serait toujours pas virtuel, car vous auriez toujours à écrire une sorte de nom de classe là-bas.

Les méthodes virtuelles, et donc abstraites, ne sont utiles que lorsque vous utilisez une variable qui, à l'exécution, peut contenir de nombreux types d'objets différents, et que vous voulez donc appeler la bonne méthode pour l'objet actuel que vous avez dans la variable. Avec les méthodes statiques, vous devez de toute façon passer par un nom de classe, donc la méthode exacte à appeler est connue au moment de la compilation car elle ne peut pas et ne changera pas.

Ainsi, les méthodes statiques virtuelles / abstraites ne sont pas disponibles dans .NET.

La source
Translate

Les méthodes statiques ne peuvent pas être héritées ou remplacées, et c'est pourquoi elles ne peuvent pas être abstraites. Les méthodes statiques étant définies sur le type, et non sur l'instance, d'une classe, elles doivent être appelées explicitement sur ce type. Ainsi, lorsque vous souhaitez appeler une méthode sur une classe enfant, vous devez utiliser son nom pour l'appeler. Cela rend l'héritage non pertinent.

Supposons que vous puissiez, pendant un moment, hériter des méthodes statiques. Imaginez ce scénario:

public static class Base
{
    public static virtual int GetNumber() { return 5; }
}

public static class Child1 : Base
{
    public static override int GetNumber() { return 1; }
}

public static class Child2 : Base
{
    public static override int GetNumber() { return 2; }
}

Si vous appelez Base.GetNumber (), quelle méthode sera appelée? Quelle valeur renvoyée? Il est assez facile de voir que sans créer d'instances d'objets, l'héritage est plutôt difficile. Les méthodes abstraites sans héritage ne sont que des méthodes qui n'ont pas de corps et ne peuvent donc pas être appelées.

La source
Translate

Un autre répondant (McDowell) a déclaré que le polymorphisme ne fonctionne que pour les instances d'objets. Cela devrait être nuancé; il existe des langages qui traitent les classes comme des instances de type "Class" ou "Metaclass". Ces langages prennent en charge le polymorphisme pour les méthodes d'instance et de classe (statiques).

C #, comme Java et C ++ avant lui, n'est pas un tel langage; lastaticLe mot clé est utilisé explicitement pour indiquer que la méthode est liée statiquement plutôt que dynamique / virtuelle.

La source
Translate

Pour ajouter aux explications précédentes, les appels de méthode statique sont liés à une méthode spécifique àau moment de la compilation, qui exclut plutôt un comportement polymorphe.

La source
Translate

Voici une situation où il y a certainement un besoin d'héritage pour les champs et méthodes statiques:

abstract class Animal
{
  protected static string[] legs;

  static Animal() {
    legs=new string[0];
  }

  public static void printLegs()
  {
    foreach (string leg in legs) {
      print(leg);
    }
  }
}


class Human: Animal
{
  static Human() {
    legs=new string[] {"left leg", "right leg"};
  }
}


class Dog: Animal
{
  static Dog() {
    legs=new string[] {"left foreleg", "right foreleg", "left hindleg", "right hindleg"};
  }
}


public static void main() {
  Dog.printLegs();
  Human.printLegs();
}


//what is the output?
//does each subclass get its own copy of the array "legs"?
La source
Translate

En fait, nous remplaçons les méthodes statiques (en delphi), c'est un peu moche, mais cela fonctionne très bien pour nos besoins.

Nous l'utilisons pour que les classes puissent avoir une liste de leurs objets disponibles sans l'instance de classe, par exemple, nous avons une méthode qui ressemble à ceci:

class function AvailableObjects: string; override;
begin
  Result := 'Object1, Object2';
end; 

C'est moche mais nécessaire, de cette façon nous pouvons instancier juste ce qui est nécessaire, au lieu d'avoir toutes les classes instanciées juste pour rechercher les objets disponibles.

C'était un exemple simple, mais l'application elle-même est une application client-serveur qui a toutes les classes disponibles sur un seul serveur, et plusieurs clients différents qui pourraient ne pas avoir besoin de tout ce que le serveur a et n'auront jamais besoin d'une instance d'objet.

C'est donc beaucoup plus facile à gérer que d'avoir une application serveur différente pour chaque client.

J'espère que l'exemple était clair.

La source
Translate

Les méthodes abstraites sont implicitement virtuelles. Les méthodes abstraites nécessitent une instance, mais les méthodes statiques n'ont pas d'instance. Ainsi, vous pouvez avoir une méthode statique dans une classe abstraite, elle ne peut tout simplement pas être statique abstraite (ou statique abstraite).

La source