Frage

Was ist der Unterschied zwischen const Und readonly und verwenden Sie eines über dem anderen?

War es hilfreich?

Lösung

Neben dem offensichtlichen Unterschied von

  • den Wert zum Zeitpunkt einer Definition für eine const VS readonly Werte berechnet dynamisch benötigen werden kann, um zu erklären, jedoch vor den Konstruktor Ausgängen zugeordnet werden .. nach, dass es gefroren ist.
  • 'const ist implizit static. Sie verwenden eine ClassName.ConstantName Notation auf sie zuzugreifen.

Es gibt einen feinen Unterschied. Betrachten wir eine Klasse in AssemblyA definiert.

public class Const_V_Readonly
{
  public const int I_CONST_VALUE = 2;
  public readonly int I_RO_VALUE;
  public Const_V_Readonly()
  {
     I_RO_VALUE = 3;
  }
}

AssemblyB Referenzen AssemblyA und verwendet diese Werte im Code. Wenn dies kompiliert,

  • im Fall des const Wertes, ist es wie ein Fund ersetzen, 2 der Wert des AssemblyB des IL ‚in gebacken‘ wird. Das bedeutet, dass morgen, wenn ich I_CONST_VALUE bis 20 in der Zukunft aktualisieren würde. AssemblyB würde noch 2 haben, bis ich es neu kompilieren .
  • im Fall des readonly Wert, ist es wie ein ref auf einen Speicherplatz. Der Wert wird nicht in AssemblyB der IL gebacken. Dies bedeutet, dass, wenn der Speicherplatz aktualisiert wird, AssemblyB den neuen Wert ohne erneute Kompilierung wird. Also, wenn I_RO_VALUE bis 30 aktualisiert wird, müssen Sie nur AssemblyA bauen. Alle Clients müssen nicht neu kompiliert werden.

Also, wenn Sie sicher sind, dass der Wert der Konstanten wird nicht Gebrauch ein const ändern.

public const int CM_IN_A_METER = 100;

Aber wenn Sie eine Konstante haben, die sich ändern kann (z w.r.t. precision) .. oder im Zweifelsfall eine readonly verwenden.

public readonly float PI = 3.14;

Update: Aku braucht eine Erwähnung Coz zu bekommen, die er diesen ersten hingewiesen. Auch muss ich stecken, wo ich das gelernt .. Effective C # - Bill Wagner

Andere Tipps

Es gibt eine Gotcha mit consts! Wenn Sie eine Konstante aus einer anderen Assembly verweisen, wird dessen Wert nach rechts in die Berufung Assembly kompiliert. Auf diese Weise, wenn Sie die Konstante in der referenzierten Assembly aktualisieren, es wird nicht in der anrufenden Anordnung ändern!

Konstanten

  • Konstanten sind statisch standardmäßig
  • Sie müssen einen Wert bei der Kompilierung-Zeit (man kann zum Beispiel 3,14 * 2, haben aber können Methoden nicht nennen)
  • Könnte innerhalb von Funktionen deklariert werden
  • in jede Baugruppe kopiert, die sie verwendet (jede Baugruppe eine lokale Kopie des Wertes wird)
  • Kann in Attribute verwendet werden

Read-only Instanzfelder

  • haben Must-Sollwert, die durch die Zeit Konstruktor Ausgänge
  • ausgewertet werden, wenn Instanz erstellt

Statische Nur-Lese-Felder

  • ausgewertet, wenn die Ausführung von Code trifft Klassenreferenz (wenn neue Instanz erstellt oder eine statische Methode ausgeführt wird)
  • muss einen bewerteten Wert durch die Zeit der statische Konstruktor erfolgt
  • Es ist nicht zu setzen Thread auf diese empfohlen (statische Konstrukteuren nur in einem Thread ausgeführt werden und wird den Wert für seine Thread gesetzt, alle anderen Threads diesen Wert haben wird nicht initialisiert)

Just hinzuzufügen, nur für Readonly Referenztypen macht die Referenz Nur-Lese nicht die Werte. Zum Beispiel:

public class Const_V_Readonly
{
  public const int I_CONST_VALUE = 2;
  public readonly char[] I_RO_VALUE = new Char[]{'a', 'b', 'c'};

  public UpdateReadonly()
  {
     I_RO_VALUE[0] = 'V'; //perfectly legal and will update the value
     I_RO_VALUE = new char[]{'V'}; //will cause compiler error
  }
}

Dies erklärt, es . Zusammenfassung:. Konst muss bei der Deklaration initialisiert werden, kann nur lesbar auf den Konstruktor initialisiert werden (und damit einen anderen Wert haben auf den Konstruktor je nach verwendetem)

EDIT: Siehe Gishu des Gotcha oben für den feinen Unterschied

const. Nirgendwohin änderbar

readonly: Dieser Wert kann nur im Konstruktor geändert werden. Kann nicht in normalen Funktionen geändert werden.

Es gibt eine kleine Gotcha mit nur lesbar. Ein Nur-Lese-Feld kann mehrere Male innerhalb des Konstruktors (en) eingestellt werden. Selbst wenn der Wert in zwei verschiedenen gekettet Konstrukteure eingestellt ist es immer noch erlaubt ist.


public class Sample {
    private readonly string ro;

    public Sample() {
        ro = "set";
    }

    public Sample(string value) : this() {
        ro = value; // this works even though it was set in the no-arg ctor
    }
}

Ein konstantes Element bei der Kompilierung festgelegt und kann nicht zur Laufzeit geändert werden. Konstanten werden als Feld deklariert, das const Schlüsselwort und muss initialisiert werden, wie sie deklariert sind.

public class MyClass
{
    public const double PI1 = 3.14159;
}

Ein readonly Mitglied ist wie eine Konstante, dass sie einen unveränderlichen Wert darstellt. Der Unterschied besteht darin, dass ein readonly Mitglied kann zur Laufzeit initialisiert werden, in einem Konstruktor, auch in der Lage sein initialisiert werden, wie sie deklariert sind.

public class MyClass1
{
     public readonly double PI2 = 3.14159;

     //or

     public readonly double PI3;

     public MyClass2()
     {
         PI3 = 3.14159;
     }
}

const

  • Sie können nicht als static deklariert werden (sie sind implizit statisch)
  • Der Wert der Konstante wird bei der Kompilierung ausgewertet
  • Konstanten werden bei der Deklaration initialisiert nur

Nur-Lese

  • Sie können entweder auf Instanzebene oder statische
  • Der Wert wird zur Laufzeit ausgewertet
  • Nur-Lese kann in Erklärung oder durch Code im Konstruktor
  • initialisiert werden

A const ist eine Übersetzungszeit konstant, während nur lesbar ein Wert in dem Konstruktor oder Feldinitialisierer zur Laufzeit berechnet und eingestellt wird. Also, ein ‚const‘ immer konstant ist, sondern ‚nur lesbar‘ ist nur lesbar, wenn es zugeordnet ist.

Hier ist ein weiterer Link zeigen, wie const nicht ist Version sicher, oder relevant für Referenztypen.

Zusammenfassung :

  • Der Wert Ihrer const Eigenschaft wird bei der Kompilierung festgelegt und kann zur Laufzeit nicht ändern
  • Const kann nicht als statisch markiert werden. - das Schlüsselwort bezeichnet sie statisch sind, im Gegensatz zu Nur-Lese-Felder, wo
  • Const kann nichts außer Wert (primitive) Typen
  • sein
  • Das Nur-Lese-Schlüsselwort markiert das Feld als unveränderlich. Jedoch kann die Eigenschaft innerhalb der Konstruktor der Klasse geändert werden
  • Die Nur-Lese-nur-Schlüsselwort kann auch mit statischen kombiniert werden, um es als const in der gleichen Art und Weise zu machen handeln (mindestens auf der Oberfläche). Es gibt einen deutlichen Unterschied, wenn Sie an der IL sehen zwischen den beiden
  • const-Felder werden als "wörtlichen" in IL markiert, während nur lesbar ist "initonly"

Read Only : Der Wert kann durch Ctor zur Laufzeit geändert werden. Aber nicht durch das Element Funktion

Konstante : Durch defult statisch. Der Wert kann nicht von jedem beliebigen Ort geändert werden (Ctor, Funktion, Laufzeit usw. no-where)

Noch eine andere gotcha. Nur-Lese-Werte können durch „abwegig“ Code durch Reflexion geändert werden

var fi = this.GetType()
             .BaseType
             .GetField("_someField", 
                       BindingFlags.Instance | BindingFlags.NonPublic);
fi.SetValue(this, 1);

Can ich wechsle ein eigenes Nur-Lese geerbt Feld in C # mithilfe von Reflektion?

Ich glaube, ein const Wert die für alle Objekte gleich ist (und muss mit einem wörtlichen Ausdruck initialisiert werden), während readonly für jede Instanziierung verschieden sein kann ...

Eines der Teammitglieder in unserem Büro zur Verfügung gestellt, die folgenden Anleitung, wann const, statisch zu verwenden und nur lesbar:

  • Mit const , wenn Sie eine Variable eines Typs Sie zur Laufzeit (Stringliteral, int, double, Aufzählungen, ...) wissen können, dass Sie alle Instanzen oder Verbraucher einer Klasse wollen hat Zugriff auf wo sollte der Wert nicht geändert werden.
  • Mit statisch , wenn Sie Daten, die Sie alle Instanzen oder Verbraucher einer Klasse haben, zugreifen möchten, wenn der Wert ändern kann.
  • Mit statischen Nur-Lese , wenn Sie eine Variable eines Typs, die Sie nicht zur Laufzeit (Objekte) wissen können, dass Sie alle Instanzen oder Verbraucher einer Klasse haben wollen Zugang zu, wenn der Wert sich nicht ändern sollte .
  • Mit Nur-Lese , wenn Sie eine Instanz Ebene Variable haben Sie zum Zeitpunkt der Objekterstellung wissen, die sich nicht ändern sollte.

Ein letzter Hinweis: a. Const Feld ist statisch, aber die Umkehrung ist nicht wahr,

Sie sind beide konstant, aber ein const ist auch bei der Kompilierung zur Verfügung. Dies bedeutet, dass ein Aspekt der Unterschied ist, dass Sie konstante Variablen verwenden können als Eingabe Konstrukteurs zuzuschreiben, aber nicht nur lesbar Variablen.

Beispiel:

public static class Text {
  public const string ConstDescription = "This can be used.";
  public readonly static string ReadonlyDescription = "Cannot be used.";
}

public class Foo 
{
  [Description(Text.ConstDescription)]
  public int BarThatBuilds {
    { get; set; }
  }

  [Description(Text.ReadOnlyDescription)]
  public int BarThatDoesNotBuild {
    { get; set; }
  }
}

Variablen const markiert sind wenig mehr als stark typisierte #define Makros, bei der Kompilierung const Variablenreferenzen mit Inline-Literalwerte ersetzt werden. Als Folge können nur bestimmte eingebaute in primitiven Werttypen auf diese Weise verwendet werden. Variablen nur lesbar gekennzeichnet ist, kann eingestellt werden, in einem Konstruktor, zur Laufzeit und ihre Nur-Lese-ness wird während der Laufzeit auch durchgesetzt werden. Es gibt einige kleinere Leistung Kosten damit verbunden, aber es bedeutet, dass Sie nur lesbar mit jeder Art verwenden können (auch Referenztypen).

Auch sind const Variablen inhärent statisch, während die Nur-Lese-Instanz-Variablen spezifisch sein können, falls gewünscht.

Ein weiterer Gotcha .

Da const Basisdatentypen funktioniert wirklich nur mit, wenn Sie mit einer Klasse arbeiten möchten, können Sie „gezwungen“ verwenden Readonly fühlen. Allerdings passen sie von der Falle! Readonly bedeutet, dass Sie nicht das Objekt mit einem anderen Objekt ersetzen können (man kann es nicht auf ein anderes Objekt verweisen machen). Aber jeder Prozess, der eine Referenz auf das Objekt hat, ist frei, um die Werte zu ändern innen das Objekt!

Also nicht verwirrt zu denken, dass Readonly ein Benutzer impliziert nicht die Dinge ändern können. Es gibt keine einfache Syntax in C # eine Instanz einer Klasse zu verhindern, dass ihre internen Werte geändert hat (soweit ich weiß).

Es ist bemerkenswerter Unterschied zwischen const und Nur-Lese-Feldern in C # .Net

const ist standardmäßig statisch und muss mit einem konstanten Wert initialisiert werden, die später nicht mehr geändert werden. Wertänderung wird in Konstrukteuren nicht erlaubt, auch. Es kann nicht mit allen Datentypen verwendet werden. Für Ex-Datetime. Es kann nicht mit Datetime-Datentyp verwendet werden.

public const DateTime dt = DateTime.Today;  //throws compilation error
public const string Name = string.Empty;    //throws compilation error
public readonly string Name = string.Empty; //No error, legal

Nur-Lese kann als statisch deklariert werden, aber nicht notwendig. Keine Notwendigkeit zum Zeitpunkt der Erklärung zu initialisieren. Sein Wert kann mit Konstruktor zugewiesen oder geändert werden. Also, es gibt Vorteile, wenn sie als Instanzklasse Element verwendet. Zwei verschiedene Instanziierung anderen Wert von Nur-Lese-Feld hat. Für die Ex -

class A
{
    public readonly int Id;

    public A(int i)
    {
        Id = i;
    }
}

Dann Nur-Lese-Feld kann mit Sofort spezifischen Werten initialisiert werden, wie folgt:

A objOne = new A(5);
A objTwo = new A(10);

Hier Instanz objOne wird Wert von Nur-Lese-Bereich hat, wie 5 und objTwo hat 10. Welche nicht möglich mit const ist.

Eine Konstante wird in die Verbraucher als Literalwert kompiliert werden, während die statische Zeichenfolge als Verweis auf den Wert dienen definiert.

Als Übung, versuchen Sie eine externe Bibliothek erstellen und konsumieren es in einer Konsolenanwendung, ändern Sie die Werte in der Bibliothek und neu kompilieren (ohne den Verbraucher Programm neu zu kompilieren), fallen die DLL in das Verzeichnis, und führen Sie manuell die EXE, Sie sollten feststellen, dass der konstante String ändert sich nicht.

Konstante

Wir müssen den Wert auf das const Feld schaffen, wenn sie definiert ist. Der Compiler speichert dann den Wert der Konstante in den Metadaten der Montage. Dies bedeutet, dass eine Konstante nur für den primitiven Typen wie boolean definiert werden kann, char, byte und so weiter. Konstanten sind immer statische Mitglieder, nicht Instanzmitglieder berücksichtigt.

Read-only

Read-only-Felder können nur zur Laufzeit aufgelöst werden. Das bedeutet, dass wir einen Wert für einen Wert definieren können den Konstruktor für die Art, in der über das Feld deklariert ist. Die Überprüfung wird vom Compiler durchgeführt, die Nur-Lese-Felder werden durch ein beliebiges anderes Verfahren als das Konstruktor nicht geschrieben.

Weitere Informationen über beide erklärt hier in diesem Artikel

CONST

  1. const Schlüsselwort kann auf Felder oder lokale Variablen angewendet werden
  2. Wir müssen zum Zeitpunkt der Deklaration const Feld zuweisen
  3. Zugeteilte Nein Speicher Da const Wert in IL-Code eingebettet ist, selbst nach der Kompilierung. Es ist wie alle Vorkommen von const-Variable finden und durch seinen Wert ersetzen. So ist der IL-Code nach der Kompilierung hartcodierte Werte anstelle von const Variablen haben, werden
  4. Const in C # ist standardmäßig statisch.
  5. Der Wert ist konstant für alle Objekte
  6. Es ist dll Versionierung Problem - Dies bedeutet, dass, wenn wir einen öffentlichen const-Variable oder Eigenschaft zu ändern, (In der Tat ist es theoretisch nicht geändert werden soll), eine andere dll oder Anordnung, die diese Variable verwendet, hat Wieder- seine gebaut
  7. Nur C # eingebauten Typen als konstant deklariert werden
  8. Const Feld kann nicht als ref oder out-Parameter übergeben werden

Readonly

  1. Nur-Lese-Schlüsselwort gilt nur für Felder nicht auf lokale Variablen
  2. Wir können zum Zeitpunkt der Deklaration oder in Konstruktor Nur-Lese-Feld zuweisen, nicht in irgendwelchen anderen Methoden.
  3. dynamischer Speicher für Nur-Lese-Felder zugeordnet und wir können den Wert während der Laufzeit erhalten.
  4. gehört Read-only auf das erstellte Objekt so durch nur Instanz der Klasse aufgerufen. Um es Teilnehmer, brauchen wir statisches Schlüsselwort hinzufügen, bevor nur lesbar.
  5. kann der Wert unterschiedlich sein, abhängig von Konstruktor verwendet wird (wie es gehört der Klasse Objekt)
  6. Wenn Sie einen nicht-primitive Typen (Referenztyp) als Nur-Lese-nur Referenz unveränderlich erklären ist nicht das Objekt enthält.
  7. Da der Wert während der Laufzeit erhalten wird, gibt es keine dll Versionierung Problem mit Nur-Lese-Felder / Eigenschaften.
  8. Wir können Nur-Lese-Feld als ref oder out-Parameter im Konstruktor Kontext übergeben.

Im Prinzip; Sie können einen Wert zu einem statischen Nur-Lese-Bereich zu einem nicht konstanten Wert zur Laufzeit zuweisen, während ein const eines konstanten Wert zugewiesen werden muss.

A const hat sein, fest codierte , wobei als readonly seine im Konstruktor gesetzt der Klasse.

Konst und ist nur lesbar ähnlich, aber sie sind nicht genau das gleiche. Ein const-Feld ist eine Compile-Zeit konstant, was bedeutet, dass dieser Wert kann zur Compile-Zeit berechnet werden. Ein Nur-Lese-Bereich ermöglicht zusätzliche Szenarien, in denen ein Code muss bei der Konstruktion des Typs ausgeführt werden. Nach dem Aufbau kann keine Nur-Lese-Bereich geändert werden.

Zum Beispiel können const Mitglieder festgelegt werden, Mitglieder wie:

struct Test
{
    public const double Pi = 3.14;
    public const int Zero = 0;
}

da Werte wie 3,14 und 0 sind Kompilierung-Konstanten. Allerdings betrachten den Fall, dass Sie einen Typ definieren und wollen einige Pre-fab Instanzen davon bieten. Zum Beispiel können Sie eine Color-Klasse und bieten „Konstanten“ für gemeinsame Farben wie Schwarz, Weiß zu definieren, etc. Es ist nicht möglich, dies mit const Mitgliedern zu tun, da die rechten Seiten sind keine Konstanten Zeit kompilieren. Man könnte dies mit regelmäßigen statischen Mitgliedern:

public class Color
{
    public static Color Black = new Color(0, 0, 0);
    public static Color White = new Color(255, 255, 255);
    public static Color Red = new Color(255, 0, 0);
    public static Color Green = new Color(0, 255, 0);
    public static Color Blue = new Color(0, 0, 255);
    private byte red, green, blue;

    public Color(byte r, byte g, byte b) {
        red = r;
        green = g;
        blue = b;
    }
}

aber dann gibt es nichts, einen Klienten von Farbe zu verhindern, damit Ausmisten, vielleicht durch die Schwarzweiss-Werte austauschen. Unnötig zu sagen, dies würde dazu führen, Betroffenheit für andere Kunden der Color-Klasse. Die „Nur-Lesen“ -Funktion Adressen dieses Szenario. Indem er einfach das Nur-Lese-Schlüsselwort in den Erklärungen der Einführung erhalten wir die flexible Initialisierung während Client-Code verhindert herumschlagen.

public class Color
{
    public static readonly Color Black = new Color(0, 0, 0);
    public static readonly Color White = new Color(255, 255, 255);
    public static readonly Color Red = new Color(255, 0, 0);
    public static readonly Color Green = new Color(0, 255, 0);
    public static readonly Color Blue = new Color(0, 0, 255);
    private byte red, green, blue;

    public Color(byte r, byte g, byte b) {
        red = r;
        green = g;
        blue = b;
    }
}

Es ist interessant festzustellen, dass const Mitglieder immer statisch sind, während ein Nur-Lese-Mitglied entweder statisch sein kann oder nicht, genau wie ein reguläres Feld.

Es ist möglich, ein einzelnes Keyword für diese beiden Zwecke zu verwenden, aber dies führt zu entweder Versionierungsprobleme oder Performance-Probleme. Nehmen wir für einen Moment, dass wir ein einziges Schlüsselwort für diese (const) verwendet und ein Entwickler schrieb:

public class A
{
    public static const C = 0;
}

und ein anderer Entwickler schrieb Code, der auf A verlassen:

public class B
{
    static void Main() {
        Console.WriteLine(A.C);
    }
}

Nun kann der Code, der sich darauf verlassen, erzeugt wird, dass A. C ist eine Kompilierung-Konstante? Das heißt, kann die Verwendung von A. C einfach durch den Wert 0 ersetzt werden? Wenn Sie mit „Ja“ sagen, dann bedeutet das, dass der Entwickler A kann nicht die Art und Weise ändern, dass A. C initialisiert wird - bindet diese in die Hände des Entwicklers von A ohne Genehmigung. Wenn Sie auf diese Frage mit „Nein“ sagen, dann eine wichtige Optimierung verpasst. Vielleicht ist der Autor von A positiv, dass A. C immer Null sein wird. Die Verwendung von sowohl const und nur lesbar ermöglicht es dem Entwickler von A die Absicht zu spezifizieren. Dies sorgt für eine bessere Versionierung Verhalten und auch eine bessere Leistung.

Readonly. Der Wert wird nur einmal aus dem Konstruktor der Klasse initialisiert werden
const: kann in jeder Funktion initialisiert werden, aber nur einmal

Der Unterschied besteht darin, dass der Wert eines statischen Nur-Lese-Feldes zur Laufzeit festgelegt wird, so dass es einen anderen Wert für die verschiedenen Ausführungen des Programms haben kann. Allerdings ist der Wert eines const Feld zu einem Kompilierung konstant eingestellt.

Denken Sie daran: Für Referenztypen in beiden Fällen (statisch und Instanz), der Nur-Lese-Modifikator verhindert, dass Sie nur von einem neuen Verweis auf das Feld zuweisen. Es ist ausdrücklich nicht unveränderlich macht das Objekt mit dem Bezug hingewiesen.

Weitere Informationen finden Sie in C # Häufig zu diesem Thema gestellte Fragen: http://blogs.msdn.com/csharpfaq/archive/2004 /12/03/274791.aspx

Konstante Variablen deklariert und bei der Kompilierung initialisiert. Der Wert kann nicht nach Stationen geändert werden. Read-only werden Variablen nur vom statischen Konstruktor der Klasse initialisiert werden. Lesen Sie wird nur nur verwendet, wenn wir den Wert zur Laufzeit zugeordnet werden soll.

Eine Sache hinzufügen, was die Leute über gesagt haben. Wenn Sie eine Baugruppe einen Nur-Lese-Wert enthält (zB Nur-Lese-MaxFooCount = 4;), können Sie den Wert ändern, dass Aufruf Baugruppen durch Versand eine neue Version dieser Versammlung mit einem anderen Wert zu sehen (zB Nur-Lese-MaxFooCount = 5;)

Aber mit einem const, wäre es in den Anrufercode gefaltet werden, wenn der Anrufer kompiliert wurde.

Wenn Sie das Niveau von C # Kenntnisse erreicht haben, sind Sie bereit für Bill Wagner Buch Effective C #: 50 Spezifische Möglichkeiten, Ihre C # zu verbessern Welche beantwortet diese Frage im Detail, (und 49 andere Dinge).

Der Hauptunterschied besteht darin, dass die C Const Äquivalent #DEFINE ist. Die Anzahl buchstäblich bekommt ein-la Precompiler substituiert ist. Read-only ist eigentlich als Variable behandelt.

Diese Unterscheidung besonders relevant, wenn Sie Project A in Abhängigkeit von einer öffentlichen Konstante von Project B. haben Angenommen, die öffentlichen ständigen Veränderungen. Jetzt ist Ihre Wahl von konst / Nur-Lese wird das Verhalten auf Projekt A auswirken:

Konst. Projekt A nicht fängt den neuen Wert (es sei denn, es mit dem neuen const, natürlich neu kompiliert wird), weil es mit den Konstanten kompiliert wurde subtituted in

Readonly. Projekt A wird immer Projekt B fragen Sie nach Variablenwert ist, so wird es den neuen Wert der öffentlichen Konstante in B abholen

Ehrlich gesagt, würde ich empfehlen Sie nur lesbar für fast alles verwenden, außer wirklich universelle Konstanten (z Pi, Inches_To_Centimeters). Für alles, was möglicherweise ändern könnte, sage ich nur lesbar verwenden.

Hope, das hilft, Alan.

In einfachen Worten ist Konst Zeit kompiliert und Nur-Lese-Zeit ausgeführt wird.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top