it-swarm.com.de

Grundlegendes zum statischen Schlüsselwort

Ich habe einige Erfahrung in der Entwicklung mit Java, Javascript und PHP.

Ich lese Schritt für Schritt Microsoft Visual C # 2010, was meiner Meinung nach ein sehr gutes Buch ist, um Sie in die C # -Sprache einzuführen.

Ich habe anscheinend Probleme beim Verständnis des statischen Schlüsselworts. Soweit ich weiß, müssen alle Methoden und Variablen statisch sein, wenn eine Klasse als statisch deklariert wird. Die Hauptmethode ist immer eine statische Methode, sodass in der Klasse, in der die Hauptmethode vorhanden ist, alle Variablen und Methoden als statisch deklariert werden, wenn Sie sie in der Hauptmethode aufrufen müssen. Außerdem habe ich festgestellt, dass Sie zum Aufrufen einer statischen Methode aus einer anderen Klasse kein Objekt erstellen müssen, für das Sie den Klassennamen verwenden können.

Aber was ist der eigentliche Zweck des statischen Schlüsselworts? Wann sollte ich statische Variablen und Methoden deklarieren?

16

Das Schlüsselwort 'static' in C # bezieht sich auf etwas in der Klasse oder auf die Klasse selbst, das von allen Instanzen der Klasse gemeinsam genutzt wird. Beispielsweise kann von allen Instanzen dieser Klasse über den Klassennamen auf ein Feld zugegriffen werden, das als statisch markiert ist.

public class SomeObject
{
    //Static Field
    static int Foo = 3;

    //instance field
    private int _Foo2 = 4;

    //instance property
    public int Foo2{get{return _Foo2;}set{_Foo2 = value;}}


    //static factory method
    public static SomeObject CreateSomeObject(int fooValue)
    {
        SomeObject retVal = new SomeObject();
        retVal.Foo2 = fooValue;
        return retVal;
    }

    //Parameterless instance constructor
    public SomeObject()
    {
    }

    public static int Add(int x)
    {
        //Static methods can only deal with local variables, or fields that
        //  are also static in the class.  This one adds x to the static member foo
        return x + Foo;

        //Foo2 is not accessable here!
    }

      //Instance method
    public int AddSomething(int x)
    {
        //Add x to the property value of Foo2
        return x + this.Foo2;

        //Note that Foo *is* accessable here as 'SomeObject.Foo'
    }

}

Ich kann ehrlich sagen, dass ich noch nie eine als statisch gekennzeichnete Klasse verwendet habe, mit Ausnahme der Erstellung von Erweiterungsmethoden ( Kurzanleitung zu Erweiterungsmethoden ).

Wie auch immer, es gibt spezielle Entwurfsmuster für die Verwendung statischer Methoden, wie z. B. Factory-Muster und Singleton-Muster , aber das Wichtigste ist, dass statische Methoden und Konstruktoren nicht behandelt werden Eine bestimmte Instanz einer Klasse (es sei denn, Sie übergeben eine), normalerweise, um Berechnungen durchzuführen oder um einen Vergleich zwischen Objekten durchzuführen. Die "Haupt" -Methode, auf die Sie sich beziehen, ist immer statisch, aber um sie aus einem anderen Blickwinkel zu betrachten, siehe diesen Artikel .

Um dies zu verfolgen, wird hier der Unterschied zwischen statischen und instanziierten Methoden, Feldern und Eigenschaften genannt.

public static void Main(string[] args)
{
    //This is a static method that starts a thread in an application
    // space.  At this point not everything actually has to be static...

    //Here is an instantiation with a parameterless contruction
    SomeObject obj = new SomeObject();

    //Here is an instantiation using a static factory method
    SomeObject obj2 = SomeObject.CreateSomeObject(3);

    //Getting field value from static field
    // Notice that this references the class name, not an instance
    int fooValue1 = SomeObject.Foo;

    //Getting property value from instance
    //  Note that this references an object instance
    int fooValue2 = obj2.Foo2;

    //Instance method must be called through an object
    obj2.AddSomething(4);  //if default constructor, would return 8

    //Static methods must be called through class name
    SomeObject.Add(4); //Returns 7
}

Überprüfen Sie auch dieser Beitrag , um einen tieferen Einblick in statische Klassen zu erhalten.

15
iMortalitySX

Hier ist Joshua Blochs Art, es zu erklären, was ich wie die meisten seiner Aussagen brillant finde (ja, ich bin ein Joshua Bloch-Fanjunge :)). Dies wird aus dem Speicher zitiert.

Stellen Sie sich vor, eine Klasse entspricht einer Blaupause für ein Haus. Stellen Sie sich dann vor, dass ein Haus zur Blaupause gehört, da eine Instanz der Klasse für die Klasse ist. Sie können eine Klasse (Blaupause) und mehrere Instanzen (Häuser) daraus erstellen lassen.

Der gesunde Menschenverstand schreibt nun vor, dass die meisten Funktionen/Verhaltensweisen, die ein Haus (eine Instanz) haben/ausführen kann, obwohl sie in der Blaupause deklariert sind, erst verwendet werden können, wenn ein tatsächliches Haus (eine Instanz) aus diesem Blau besteht -print (Klasse). Ihre Blaupause enthält möglicherweise die Stelle, an der die Lichtschalter und die Glühbirnen angebracht werden sollen, aber Sie haben keine Möglichkeit, diese Arbeiten an der Blaupause durchzuführen. Sie müssen das Haus tatsächlich bauen, um in der Lage zu sein um den Lichtschalter ein- und auszuschalten und bestimmte Glühbirnen ein- und auszuschalten.

Möglicherweise haben Sie jedoch ein Verhalten, das direkt auf die Blaupause anwendbar ist und das Sie direkt auf der Blaupause verwenden/darauf zugreifen können, ohne aus dieser Blaupause ein tatsächliches Haus machen zu müssen. Stellen Sie sich vor, Ihre Blaupause verfügt über eine Schaltfläche, die beim Drücken den Fußabdruck des in dieser Blaupause enthaltenen Hauses anzeigt (indem Sie alle Längen der Wände und dergleichen berechnen). Natürlich KÖNNTEN Sie zuerst ein Haus bauen und dann den Fußabdruck messen, aber Sie können dies nur mit der Blaupause tun. Daher wäre es hilfreicher, dieses Verhalten in der Blaupause zu implementieren. Eine solche eingebettete Schaltfläche mit Blaupause, die den Fußabdruck des Hauses berechnet, entspricht einer statischen Funktion in einer Klasse.

19
Shivan Dragon

Wenn ich es so betrachte, hilft es mir:

  • Jeder Typ hat eine statische Instanz.
  • Die statische Instanz wird beim ersten Zugriff auf den Typ erstellt - entweder über die statische Instanz oder durch Erstellen einer anderen Instanz.
  • Sie können beliebig viele nicht statische Instanzen erstellen, es gibt jedoch nur eine statische Instanz.
  • Alles innerhalb einer Klasse, das als statisch deklariert ist, gehört zur statischen Instanz und hat daher keinen Zugriff auf andere von Ihnen erstellte Instanzen. Die anderen Instanzen haben jedoch Zugriff auf die statische Instanz.
  • Wenn eine Klasse als statisch deklariert ist, können Sie keine anderen Instanzen erstellen, sondern nur die statische Instanz.
  • Sie können einen statischen Konstruktor für die statische Instanz genau wie einen Konstruktor für eine normale Instanz deklarieren (indem Sie ihn jedoch als statisch deklarieren).

Wann sollte das statische Schlüsselwort verwendet werden?

  • Jede Methode, die keinen Zugriff auf lokale Eigenschaften benötigt, kann und sollte als statisch deklariert werden.
  • Hilfsklassen, die überhaupt keinen Status haben (was sowieso selten sein sollte) und die niemals verspottet werden, können als statisch deklariert werden. Ob sie sollten, ist eine andere Sache; Verwenden Sie diese Funktionalität sparsam.
  • Eigenschaften und Felder, auf die alle Instanzen einer Klasse zugreifen müssen, müssen als statisch deklariert werden. Verwenden Sie dies jedoch nur, wenn es keine andere Option gibt.
12
pdr

Einfachste Erklärung --- Statisch => Pro Umgebung existiert nur eine Kopie.

Innerhalb einer VM oder CLR) gibt es also immer nur eine Kopie einer statischen Klasse, und jede andere Klasse, die darauf verweist, muss ihre Methoden und Daten mit allen anderen Klassen teilen, die darauf verweisen.

Für eine statische Variable gibt es in der Laufzeitumgebung nur eine Instanz dieser Variablen, unabhängig davon, wie viele Kopien der besitzenden Klasse erstellt werden, wenn sie auf eine statische Variable verweisen. Sie verweisen alle auf dasselbe Speicherelement.

4
James Anderson

Statische Mitglieder sind der Klasse zugeordnet, nicht einer Instanz dieser Klasse.

Da es sich um .Net handelt, sollten Sie die Klassen String berücksichtigen, insbesondere die Methoden Split und Join.

Split ist eine Instanzmethode . Erstellen Sie eine String-Variable, geben Sie ihr einen Wert, und Sie können Split () für diese Variable/diesen Wert aufrufen und ein Array von "Bits" zurückerhalten:

String s1 = "abc,def,ghi" ; 
String[] array2 = s1.Split( ',' ) ; 

So ist beispielsweise für Methoden der Wert innerhalb der angegebenen Klasseninstanz von Bedeutung .

Join ist eine statische Methode. OK, es ergibt ein String -Ergebnis , wenn ein Trennzeichen und ein String-Array zum Kauen angegeben werden. Es hat also "etwas mit" der String-Klasse zu tun. aber es ist nicht mit einem bestimmten Wert in einer String-Instanz verbunden (in der Tat) , Instanzwerte stehen statischen Methoden nicht zur Verfügung).
In anderen Sprachen wurde die Join-Methode möglicherweise auf die Array-Klasse (oder besser auf eine StringArray-Klasse) "geklebt", aber unsere Freunde in Redmond entschieden, dass sie für die String-Klasse "relevanter" ist. Also legten sie es dort hin.

String[] array3 = { ... } 
s1 = String.Join( array3, "," ) ; 

Eine andere Alternative könnte darin bestehen, eine Instanz Join-Methode zu haben, bei der der Wert in der von uns als Verbindungsbegrenzer verwendeten Zeichenfolge [Klasseninstanz] verwendet wird ::

// Maybe one day ... 
String s4 = "," ; 
s1 = s4.Join( array3 ) ; 
2
Phill W.

Das Schlüsselwort static kann für Neulinge etwas schwer zu verstehen sein. Sein Hauptzweck besteht darin, ein Klassenmitglied als nicht zu einer einzelnen Instanz der Klasse gehörend, sondern zur Klasse selbst zu identifizieren.

Ohne zu sehr ins Detail zu gehen, setzen C # (und Java) das objektorientierte Ideal, dass alle Codes und Daten zu einem Objekt gehören müssen, strikt durch und sind daher in Umfang, Sichtbarkeit und Lebensdauer begrenzt. Dies ist im Allgemeinen die beste Vorgehensweise, wenn der grundlegende Grundsatz eines Objekts gilt, das eine reale Sache darstellt. Dies ist jedoch nicht immer der Fall. Manchmal benötigen Sie eine Funktion oder Variable, die Sie von überall im Code aus aufrufen können, ohne dass Sie einen Verweis auf ein Objekt, das ihn enthält, weitergeben müssen, und mit der Garantie, dass die Daten, die Sie suchen at oder change ist gena was alle anderen zu tun haben und keine Kopie davon, die zu einer anderen Instanz eines Objekts gehört.

Ein solches Verhalten war in C und C++ in Form der "globalen" Funktion oder Variablen verfügbar, die nicht in einem Objekt gekapselt war. Als Kompromiss unterstützen C # und Java "statischen Bereich", einen halben Punkt zwischen wirklich globalem Code ohne übergeordnetes Objekt und Instanzmitgliedern mit eingeschränktem Bereich.

Jedes als static deklarierte "Code-Mitglied" (Funktion, Eigenschaft, Feld) wird ab der ersten Zeile der Funktion main() des Programms in den Gültigkeitsbereich aufgenommen und verlässt es erst mit der Funktion main() Funktion wird beendet. Im Klartext ist ein statisches Element vorhanden, das verwendet werden kann, solange das Programm ausgeführt wird. Darüber hinaus werden statische Mitglieder aufgerufen, indem sie als Mitglieder des Typs selbst aufgerufen werden, nicht als Mitglieder einer Instanz dieses Typs:

public class Foo
{
   public int MyInt {get;set;} //this is an "instance member"
   public static int MyStaticInt {get;set;} //this is a "static member"
}

...

var myFoo = new Foo();
myFoo.MyInt = 5; //valid
myFoo.MyStaticInt = 5; //invalid; MyStaticInt doesn't belong to any one Foo

Foo.MyInt = 5; //invalid; MyInt only has meaning in the context of an instance
Foo.MyStaticInt = 2; //valid

Dadurch werden statische Elemente für jeden Code sichtbar, der Kenntnis vom Typ hat, unabhängig davon, ob er eine einzelne Instanz davon kennt oder nicht.

Um Ihre Frage zu beantworten, besteht der Hauptvorteil des Markierens von etwas als statisch darin, dass es überall dort sichtbar wird, wo der Typ selbst bekannt ist, unabhängig davon, ob der konsumierende Code eine Instanz des enthaltenen Objekts hat oder erhalten kann. Es gibt auch einen geringfügigen Leistungsvorteil; Da sich die Methode im statischen Bereich befindet, kann sie nur auf andere statische Elemente (derselben oder anderer Klassen) und auf alles zugreifen, was als Parameter übergeben wird. Daher muss die Laufzeit keinen Verweis auf die aktuelle Instanz des enthaltenen Objekts auflösen, wie dies normalerweise für eine Instanzmethode erforderlich wäre, um kontextspezifische Statusinformationen bereitzustellen.

Ganze Klassen können auch als statisch markiert werden. Auf diese Weise teilen Sie dem Compiler mit, dass die Klassendeklaration nur aus statischen Elementen besteht und daher nicht instanziiert werden kann. Auf diese Weise können Sie auf einfache Weise sicherstellen, dass sich nur eine Kopie eines Objekts im Speicher befindet. mach die Klasse und alles darin statisch. Es ist jedoch sehr selten, dass dies die beste Lösung für einen solchen Bedarf ist. In einer Situation, in der genau eine Kopie eines Datensatzes erforderlich ist, wird normalerweise stattdessen der "Singleton" empfohlen. Dies ist eine nicht statische Klasse, die einen statischen Accessor und einen nicht öffentlichen Konstruktor verwendet, um den Zugriff auf eine einzelne Instanz von sich selbst zu ermöglichen. Theoretisch bietet ein Singleton fast die gleichen Vorteile wie eine vollständig statische Klasse, bietet jedoch die zusätzliche Möglichkeit, die Klasse instanzbasiert und objektorientiert zu verwenden.

2
KeithS