Methoden Teil 1 – Konstruktoren in C#

Methoden Teil 1 – Konstruktoren in C#

Konstruktoren in C#

In dieser Artikelserie möchte ich die verschiedenen Arten von Methoden behandeln, die im .NET-Framework vorhanden sind. Der erste Methodentyp, den ich behandeln möchte, sind die Konstruktoren in C#. Ja, Konstruktoren sind auch die Methoden, deren Namen und Rückgabetypen nur auf den Namen der Klasse reduziert wurden. Konstruktoren in C# wurden verwendet, um die Werte von Datenelementen sowie Elementvariablen der Klasse zu erstellen. In diesem Artikel werde ich auf alle wichtigen Punkte im Zusammenhang mit Konstruktoren eingehen. Beginnen wir nacheinander.

CodeProject

Bevor Sie mit dem Artikel beginnen, sollten Sie sich hier über Referenztypen und Werttypen informieren.

  1. Wie bereits erwähnt, sind Konstruktoren die Methoden, die es ermöglichen, Instanzen des Typs zu initialisieren und die lokalen Datenelemente auf ihre Anfangs- oder Standardwerte zu setzen. Bitte sehen Sie sich das Codebeispiel unten an
       public class MyClass
       {
           private int intVar = 5;
       }
    

    Sehen Sie sich nun den IL-Code an, den ich mit ILDasm.exe generiert habe. Hier können wir deutlich sehen, dass ein Konstruktor für die MyClass erstellt wird die die intVar’s lädt Wert im Speicher und ruft danach den Konstruktor der Basisklasse auf. Außerdem können wir sehen, dass der Konstruktor als Methode definiert ist.

  2. Für einige Leute ist es immer ein Punkt der Verwirrung, ob der Konstruktor zuerst aufgerufen oder der Speicher zuerst zugewiesen wird. Es ist wichtig zu beachten, dass zum Erstellen der Instanzen des Typs immer zuerst Konstruktoren aufgerufen werden, um die Menge an Speicher zu berechnen, die für die Datenfelder der Instanz erforderlich ist. Vor dem Aufruf des Konstruktors des Typs wird der Speicherplatz für diesen Typ beurteilt. Nach all diesen Prozessen wird der Speicher für den Typ im Heap-Speicher zugewiesen.
  3. Konstruktor als Methoden können nicht vererbt werden.
  4. Da Konstruktoren nicht vererbt werden können, sind virtuelle, neue, überschreibende, versiegelte oder abstrakte Schlüsselwörter für Konstruktoren nicht erlaubt.
  5. Wenn der Benutzer keinen Konstruktor definiert hat, definiert der Compiler in diesem Fall automatisch den Standardparameter ohne Konstruktor, wie in Punkt 1 erwähnt, der den Parameter ohne Konstruktor der Basisklasse aufruft. Auf diese Weise wird der Klassenkonstruktor von System.Object zuerst aufgerufen. Ich habe den folgenden Codeausschnitt erstellt, um die Konstruktoren und die Art und Weise, wie sie initialisiert werden, besser zu verstehen
    public class MyBaseClass
        {
            public int myLocalVar = 10;
    
            public MyBaseClass()
            {
                Console.WriteLine("Base Class myLocalVar Value: " + myLocalVar);
                myLocalVar = 20;
                Console.WriteLine("Base Class Constructor's myLocalVar Value: " + myLocalVar);
            }
        }
    
        public class MyDerivedClass : MyBaseClass
        {      
            public MyDerivedClass()
            {
                myLocalVar = 30;
                Console.WriteLine("Base class's myLocalVar value :" + myLocalVar);
                Console.Read();
            }
        }

    Der obige Code zeigt die Reihenfolge, in der Konstruktoren initialisiert werden. Wenn ich eine Instanz der abgeleiteten Klasse wie unten gezeigt erstelle. Dies ist auch das Szenario, wie sich die Konstruktoren im Falle einer Vererbung verhalten.

                MyDerivedClass derivedClass = new MyDerivedClass();
    
    

    Die Ausgabe des obigen Codes sieht wie unten gezeigt aus ,

    Wie wir aus der Ausgabe sehen können, ist die Elementvariable der Basisklasse diejenige, die zuerst initialisiert wird, und danach wird der Konstruktor der Basisklasse und dann der Konstruktor der abgeleiteten Klasse aufgerufen.

  6. Wenn die Klasse abstrakt ist, hat der Standardkonstruktor in diesem Fall geschützte Zugänglichkeit, andernfalls hat der Konstruktor öffentliche Zugänglichkeit.
  7. Wenn in der Basisklasse kein parameterloser Konstruktor vorhanden ist, hat der Compiler in diesem Fall den Kompilierzeitfehler generiert, wie im folgenden Code gezeigt.

    Der Fehler kann durch Aufrufen der behoben werden Basisklassenkonstruktor explizit wie unten gezeigt,

    public class MyDerivedClass : MyBaseClass
        {
            public MyDerivedClass(int localvar):base(localvar)
            {
    
            }
        }
    
  8. Die gleichen Klassenkonstruktoren können mit dem Schlüsselwort this aufgerufen werden. Dieses Szenario kann nützlich sein, um alle Instanzfelder in einem einzelnen Konstruktor zu initialisieren, wenn wir mehrere Konstruktoren in einer Klasse definiert haben. Es ist immer ratsam, alle Instanzfelder in einem einzigen parameterlosen Konstruktor zu initialisieren, anstatt sie gleichzeitig bei der Deklaration zu initialisieren (was besser als Inline-Instanzfeldinitialisierung bekannt ist). Das Codebeispiel lautet wie folgt.
        public class MyClass
        {
            private int intVar;
            private string stringvar;
            private double doubleVar;      
    
    
            public MyClass()
            {
                intVar = 5;
                stringvar = "Hello";
                doubleVar = 3.14;
            }
    
            public MyClass(int x):this()
            {
    
            }
    
            public MyClass(string y):this()
            {
    
            }
        }
    
  9. Parameterlose Konstruktoren sind für Werttypen in C# nicht erlaubt, wie wir aus dem Code unten sehen können, wird bei jedem Versuch ein Kompilierzeitfehler generiert

    Aber wir können definitiv Konstruktoren mit Parametern haben für Werttypen und diese Konstruktoren werden nur aufgerufen, wenn wir sie explizit aufrufen, andernfalls werden den Werttypen die Werte 0 oder NULL zugewiesen.

    Codebeispiel für die Werttypstruktur.

        public struct MyStruct
        {
            public MyStruct(int x)
            {
    
            }
        }
    

Nachdem ich über alle Konzepte zu den Konstruktoren gesprochen habe, möchte ich über die verschiedenen Arten von Konstruktoren sprechen, die wir in C# erstellen können.

  1. Statische Konstruktoren –

    Da wir wissen, dass Instanzkonstruktoren verwendet werden, um die Datenmember einer Klasse zu initialisieren, werden die Konstruktoren des Typs (statisch) verwendet, um die statischen Datenmember und Membervariablen des Typs zu initialisieren, dh sie werden verwendet, um den Anfangszustand eines Typs und festzulegen nicht seine Instanz.
    Standardmäßig sind innerhalb eines Typs keine Typkonstruktoren definiert, und wenn wir einen Typkonstruktor haben wollen, können wir nicht mehr als einen in einem einzelnen Typ haben. Außerdem nehmen Typkonstruktoren keine Parameter entgegen.
    Typ(statische) Konstruktoren für Referenztypen und Werttypen werden unten definiert

        public class MyClass
        {
            static MyClass()
            {
    
            }
        }
    
    
        public struct MyStruct
        {
            static MyStruct()
            {
    
            }
        }
    

    Wie wir aus dem obigen Codeausschnitt sehen können, haben die Typkonstruktoren keine Zugriffsmodifikatoren. Diese Konstruktoren sind standardmäßig privat, um zu verhindern, dass Entwicklercode sie aufruft.

    Wenn statische Konstruktoren öffentlich wären, hätte dies viele subtile Fehler im Code verursachen können. Als Erstes ruft CLR diese statischen Konstruktoren auf, während sie auf die erste Instanz der Klasse verweist.

    Der Aufruf des Typkonstruktors ist eine knifflige Sache, auf die ich hier eingehen möchte. Wenn der Just-in-Time-Compiler (JIT) einen Methodencode kompiliert, sieht er, auf welche Typen im Code verwiesen wird und ob einer der Typen einen (statischen) Typkonstruktor definiert. Der Compiler prüft, ob der statische Konstruktor des Typs bereits für diese App-Domäne ausgeführt wurde. Wenn der Konstruktor noch nie ausgeführt wurde, ruft der Compiler den statischen Konstruktor auf und initialisiert alle statischen Felder der Klasse. Wenn der statische Konstruktor in diesem Fall bereits aufgerufen wurde, hat der Compiler ihn nie wieder ausgeführt.

    Was ist, wenn viele Threads denselben Konstruktor ausführen wollen?

    In dieser Art von Szenario, in dem mehrere Threads gleichzeitig dieselbe Methode ausführen, die auf unsere Klasse mit einem statischen Konstruktor verweist, stellt die CLR sicher, dass der statische Konstruktor nur einmal pro AppDomain ausgeführt wird. Um dies sicherzustellen, erwirbt der aufrufende Thread beim Aufruf eines statischen Konstruktors eine sich gegenseitig ausschließende Thread-Synchronisationssperre. Wenn also mehrere Threads gleichzeitig versuchen, den statischen Konstruktor eines Typs aufzurufen, erhält nur ein Thread die Sperre und andere Threads werden blockiert. Der erste Thread führt den statischen Konstruktor aus. Nachdem der erste Thread den Konstruktor verlassen hat, wachen die wartenden Threads auf und sehen, dass der Code des Konstruktors bereits ausgeführt wurde, und sie werden den Code nicht erneut ausführen.

    Als Beispiel für die Verwendung der statischen Konstruktoren möchte ich einen Codeausschnitt zeigen, der im Grunde eine Datencontainerklasse ist, die auf der Datenliste arbeitet. Als Sicherheit müssen alle Funktionen dieser Klasse, die auf dieser Datenliste arbeiten, eine vorbelegte Liste haben. Dies kann durch einen statischen Konstruktor in der Klasse erreicht werden. Bitte werfen Sie einen Blick auf den Code unten.

    public static class DataContainer
        {
            private static IList list;
    
            static DataContainer()
            {
                list = new List() { 1, 2, 3};
            }
    
            public static void AddItem(int intvar)
            {
                list.Add(intvar);
            }
    
            public static int RetrieveItemAt(int position)
            {
                if (list.Count > position)
                    return list[position];
                else
                    return -1;
            }
         }
    

    In Ermangelung des statischen Konstruktors müssen wir eine Methode verwendet haben, die die Liste initialisieren und füllen sollte, in diesem Fall gibt es gute Chancen, diese Funktion selbst aufzurufen.

  2. Private Konstrukteure

    Private Konstruktoren in C# werden in einer Klasse verwendet, um zu verhindern, dass eine Instanz der Klasse von außerhalb der Klasse erstellt wird.

    Eines der Szenarien, in denen ich einen privaten Konstruktor verwenden möchte, ist, dass mein gesamter Initialisierungscode in nur einem Konstruktor vorhanden sein soll und ich diesen Konstruktor nicht von außen aufrufen lassen möchte diese Klasse, wie im folgenden Code gezeigt.

        public class MyClass
        {
            private int intVar;
            private string stringvar;
            private double doubleVar;
    
    
            private MyClass()
            {
                intVar = 5;
                stringvar = "Hello";
                doubleVar = 3.14;
            }
    
            public MyClass(int x)
                : this()
            {
    
            }
    
            public MyClass(string y)
                : this()
            {
    
            }
         }
    

    Ein weiterer Fall, in dem wir häufig private Konstruktoren verwenden, sind Singleton-Klassen. Dies sind die Klassen, die in der gesamten Anwendung nur eine einzige Instanz von sich selbst verwalten. Private Konstrukteure erlauben es uns, dies wie im folgenden Code gezeigt zu tun .

        public class Singleton
        {
            private static Singleton _Singleton;
            private Singleton()
            {
    
            }
    
            public static Singleton GetInstance()
            {
                if (_Singleton == null)
                    _Singleton = new Singleton();
    
                return _Singleton;
            }
        }
    

Das ist alles, was ich über die Konstrukteure diskutieren möchte. Ich hoffe, dieser Artikel hat Ihnen geholfen, die Konstruktoren und ihre Konzepte zu verstehen. Bitte lassen Sie mich wissen, was Sie über den Artikel denken oder ob ich etwas vergessen habe, das ich in diesen Artikel aufnehmen sollte.