.net - Warum kann ich in C # keine abstrakten statischen Methoden haben?

Translate

Ich habe mit gearbeitetAnbieterIn letzter Zeit stieß ich auf eine interessante Situation, in der ich eine abstrakte Klasse mit einer abstrakten statischen Methode haben wollte. Ich habe ein paar Beiträge zu diesem Thema gelesen und es hat irgendwie Sinn gemacht, aber gibt es eine schöne klare Erklärung?

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

Alle Antworten

Translate

Statische Methoden gibt es nichtinstanziiertAls solche sind sie nur ohne Objektreferenz verfügbar.

Ein Aufruf einer statischen Methode erfolgt über den Klassennamen, nicht über eine Objektreferenz, und der IL-Code (Intermediate Language) zum Aufrufen ruft die abstrakte Methode über den Namen der Klasse auf, die sie definiert hat, nicht unbedingt über den Namen von die Klasse, die Sie verwendet haben.

Lassen Sie mich ein Beispiel zeigen.

Mit folgendem Code:

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

public class B : A
{
}

Wenn Sie B.Test wie folgt aufrufen:

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

Dann lautet der tatsächliche Code in der Main-Methode wie folgt:

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

Wie Sie sehen, wird A.Test aufgerufen, da es die A-Klasse war, die ihn definiert hat, und nicht B.Test, obwohl Sie den Code auf diese Weise schreiben können.

Wenn du hättestKlassentypenWie in Delphi, wo Sie eine Variable erstellen können, die sich auf einen Typ und nicht auf ein Objekt bezieht, hätten Sie mehr Verwendung für virtuelle und damit abstrakte statische Methoden (und auch Konstruktoren), aber sie sind nicht verfügbar und daher sind statische Aufrufe nicht verfügbar -virtual in .NET.

Mir ist klar, dass die IL-Designer zulassen könnten, dass der Code kompiliert wird, um B.Test aufzurufen, und den Aufruf zur Laufzeit auflösen, aber er wäre immer noch nicht virtuell, da Sie dort immer noch einen Klassennamen schreiben müssten.

Virtuelle und damit abstrakte Methoden sind nur dann nützlich, wenn Sie eine Variable verwenden, die zur Laufzeit viele verschiedene Objekttypen enthalten kann, und daher die richtige Methode für das aktuelle Objekt in der Variablen aufrufen möchten. Bei statischen Methoden müssen Sie ohnehin einen Klassennamen durchlaufen, sodass die genaue aufzurufende Methode zur Kompilierungszeit bekannt ist, da sie sich nicht ändern kann und wird.

Daher sind virtuelle / abstrakte statische Methoden in .NET nicht verfügbar.

Quelle
Translate

Statische Methoden können nicht vererbt oder überschrieben werden, weshalb sie nicht abstrakt sein können. Da statische Methoden für den Typ und nicht für die Instanz einer Klasse definiert sind, müssen sie für diesen Typ explizit aufgerufen werden. Wenn Sie also eine Methode für eine untergeordnete Klasse aufrufen möchten, müssen Sie ihren Namen verwenden, um sie aufzurufen. Dies macht die Vererbung irrelevant.

Angenommen, Sie könnten für einen Moment statische Methoden erben. Stellen Sie sich dieses Szenario vor:

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; }
}

Wenn Sie Base.GetNumber () aufrufen, welche Methode würde aufgerufen? Welcher Wert wurde zurückgegeben? Es ist ziemlich leicht zu erkennen, dass die Vererbung ohne das Erstellen von Instanzen von Objekten ziemlich schwierig ist. Abstrakte Methoden ohne Vererbung sind nur Methoden, die keinen Körper haben und daher nicht aufgerufen werden können.

Quelle
Translate

Ein anderer Befragter (McDowell) sagte, dass Polymorphismus nur für Objektinstanzen funktioniert. Das sollte qualifiziert sein; Es gibt Sprachen, die Klassen als Instanzen eines Typs "Klasse" oder "Metaklasse" behandeln. Diese Sprachen unterstützen den Polymorphismus sowohl für Instanz- als auch für Klassenmethoden (statisch).

C # ist wie Java und C ++ zuvor keine solche Sprache. dasstaticDas Schlüsselwort wird explizit verwendet, um anzuzeigen, dass die Methode eher statisch als dynamisch / virtuell gebunden ist.

Quelle
Translate

Um die vorherigen Erläuterungen zu ergänzen, werden statische Methodenaufrufe an eine bestimmte Methode unter gebundenKompilierungszeit, was polymorphes Verhalten eher ausschließt.

Quelle
Translate

Hier ist eine Situation, in der definitiv eine Vererbung für statische Felder und Methoden erforderlich ist:

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"?
Quelle
Translate

Wir überschreiben tatsächlich statische Methoden (in Delphi), es ist ein bisschen hässlich, aber es funktioniert gut für unsere Bedürfnisse.

Wir verwenden es, damit die Klassen eine Liste ihrer verfügbaren Objekte ohne die Klasseninstanz haben können. Wir haben beispielsweise eine Methode, die folgendermaßen aussieht:

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

Es ist hässlich, aber notwendig. Auf diese Weise können wir genau das instanziieren, was benötigt wird, anstatt alle Klassen instanziieren zu lassen, nur um nach den verfügbaren Objekten zu suchen.

Dies war ein einfaches Beispiel, aber die Anwendung selbst ist eine Client-Server-Anwendung, bei der alle Klassen auf nur einem Server verfügbar sind und mehrere verschiedene Clients, die möglicherweise nicht alles benötigen, was der Server hat, und niemals eine Objektinstanz benötigen.

Dies ist also viel einfacher zu warten, als für jeden Client eine andere Serveranwendung zu haben.

Hoffe das Beispiel war klar.

Quelle
Translate

Die abstrakten Methoden sind implizit virtuell. Abstrakte Methoden erfordern eine Instanz, statische Methoden haben jedoch keine Instanz. Sie können also eine statische Methode in einer abstrakten Klasse haben, sie kann einfach nicht statisch abstrakt (oder abstrakt statisch) sein.

Quelle