Hoe maak je constructor chaining in C#

Ik weet dat dit zogenaamd een supereenvoudige vraag is, maar ik worstel al een tijdje met het concept.

Mijn vraag is, hoe koppel je constructors in C#?

Ik zit in mijn eerste OOP-les, dus ik ben net aan het leren. Ik begrijp niet hoe constructor chaining werkt of hoe het te implementeren of zelfs waarom het beter is dan alleen constructors te doen zonder chaining.

Ik zou graag wat voorbeelden met uitleg op prijs stellen.

Dus hoe koppel je ze aan elkaar?
Ik weet dat het met twee gaat:

public SomeClass this: {0}
public SomeClass
{
    someVariable = 0
} 

Maar hoe doe je dat met drie, vier enzovoort?

Nogmaals, ik weet dat dit een beginnersvraag is, maar ik heb moeite om dit te begrijpen en ik weet niet waarom.


Antwoord 1, autoriteit 100%

Je gebruikt de standaardsyntaxis (gebruikt thisals een methode) om de overbelasting te kiezen, binnende klasse:

class Foo 
{
    private int id;
    private string name;
    public Foo() : this(0, "") 
    {
    }
    public Foo(int id, string name) 
    {
        this.id = id;
        this.name = name;
    }
    public Foo(int id) : this(id, "") 
    {
    }
    public Foo(string name) : this(0, name) 
    {
    }
}

dan:

Foo a = new Foo(), b = new Foo(456,"def"), c = new Foo(123), d = new Foo("abc");

Let ook op:

  • u kunt aan constructors op het basistype ketenen met behulp van base(...)
  • je kunt extra code in elke constructor plaatsen
  • de standaardinstelling (als u niets opgeeft) is base()

voor “waarom?”:

  • Code reductie (altijd een goede zaak)
  • Noodzakelijk Om een ​​niet-standaard basisconstructeur te bellen, bijvoorbeeld:

    SomeBaseType(int id) : base(id) {...}
    

Merk op dat u ook op een vergelijkbare manier objecti-initializers kunt gebruiken (zonder iets hoeft te schrijven):

SomeType x = new SomeType(), y = new SomeType { Key = "abc" },
         z = new SomeType { DoB = DateTime.Today };

Antwoord 2, Autoriteit 16%

Ik wil gewoon een geldig punt ophalen naar iedereen die hiervoor zoekt. Als u gaat werken met .NET-versies vóór 4.0 (vs2010), kunt u geadviseerd worden dat u constructoreketens moet maken zoals hierboven weergegeven.

Als u echter in 4.0 verblijft, heb ik goed nieuws. U kunt nu een enkele constructeur hebben met optionele argumenten! Ik zal het voorbeeld van de Foo Class vereenvoudigen:

class Foo {
  private int id;
  private string name;
  public Foo(int id = 0, string name = "") {
    this.id = id;
    this.name = name;
  }
}
class Main() {
  // Foo Int:
  Foo myFooOne = new Foo(12);
  // Foo String:
  Foo myFooTwo = new Foo(name:"Timothy");
  // Foo Both:
  Foo myFooThree = new Foo(13, name:"Monkey");
}

Wanneer u de constructor implementeert, kunt u de optionele argumenten gebruiken, aangezien standaardinstellingen zijn ingesteld.

Ik hoop dat je genoten hebt van deze les! Ik kan gewoon niet geloven dat ontwikkelaars klagen over het bouwen van chainen en niet in staat zijn om de standaard optionele argumenten sinds 2004/2005 te gebruiken! Nu heeft het zo lang genomen in de ontwikkelingswereld, dat ontwikkelaars bang zijn om het te gebruiken omdat het niet achterwaarts compatibel zal zijn.


Antwoord 3, autoriteit 8%

Dit wordt het best geïllustreerd met een voorbeeld. Imaging we hebben een klas Persoon

public Person(string name) : this(name, string.Empty)
{
}
public Person(string name, string address) : this(name, address, string.Empty)
{
}
public Person(string name, string address, string postcode)
{
    this.Name = name;
    this.Address = address;
    this.Postcode = postcode;
}

Dus hier hebben we een constructor die enkele eigenschappen instelt, en constructor-chaining gebruikt om je in staat te stellen het object te maken met alleen een naam, of alleen een naam en adres. Als u een instantie maakt met alleen een naam, wordt er een standaardwaarde, string.Empty through naar de naam en het adres verzonden, die vervolgens een standaardwaarde voor Postcode doorstuurt naar de uiteindelijke constructor.

Hierdoor verminder je de hoeveelheid code die je hebt geschreven. Slechts één constructor heeft daadwerkelijk code, je herhaalt jezelf niet, dus als je bijvoorbeeld Naam verandert van een eigenschap naar een intern veld, hoef je maar één constructor te wijzigen – als je die eigenschap in alle drie de constructors zou instellen dat zijn drie plaatsen om het te veranderen.


Antwoord 4, autoriteit 3%

Wat is het gebruik van “Constructor Chain”?
Je gebruikt het om de ene constructor van een andere constructor aan te roepen.

Hoe kan “Constructor Chain” worden geïmplementeerd?
Gebruik het trefwoord “: this (yourProperties)” na de definitie van constructor. bijvoorbeeld:

Class MyBillClass
{
    private DateTime requestDate;
    private int requestCount;
    public MyBillClass()
    {
        /// ===== we naming "a" constructor ===== ///
        requestDate = DateTime.Now;
    }
    public MyBillClass(int inputCount) : this()
    {
        /// ===== we naming "b" constructor ===== ///
        /// ===== This method is "Chained Method" ===== ///
        this.requestCount= inputCount;
    }
}

Waarom is het nuttig?
Belangrijke reden is het verminderen van codering en het voorkomen van dubbele code. zoals herhaalde code voor het initialiseren van eigenschap
Stel dat een eigenschap in de klasse moet worden geïnitialiseerd met een specifieke waarde (in ons voorbeeld requestDate). En klasse heeft 2 of meer constructeurs. Zonder “Constructor Chain”, moet u de initialisatiecode herhalen in alle aannemers van de klas.

Hoe werkt het? (Of, wat is de uitvoeringsvolgorde in “Constructor Chain”)?
in het bovenstaande voorbeeld zal methode “a” eerst worden uitgevoerd, en dan keert de instructiereeks terug naar methode “b”.
Met andere woorden, bovenstaande code is gelijk aan onderstaande:

Class MyBillClass
{
    private DateTime requestDate;
    private int requestCount;
    public MyBillClass()
    {
        /// ===== we naming "a" constructor ===== ///
        requestDate = DateTime.Now;
    }
    public MyBillClass(int inputCount) : this()
    {
        /// ===== we naming "b" constructor ===== ///
        // ===== This method is "Chained Method" ===== ///
        /// *** --- > Compiler execute "MyBillClass()" first, And then continue instruction sequence from here
        this.requestCount= inputCount;
    }
}

Antwoord 5, autoriteit 3%

Ik heb een dagboekles en dus schrijf ik niet steeds opnieuw de waarden in te stellen

public Diary() {
    this.Like = defaultLike;
    this.Dislike = defaultDislike;
}
public Diary(string title, string diary): this()
{
    this.Title = title;
    this.DiaryText = diary;
}
public Diary(string title, string diary, string category): this(title, diary) {
    this.Category = category;
}
public Diary(int id, string title, string diary, string category)
    : this(title, diary, category)
{
    this.DiaryID = id;
}

Antwoord 6, autoriteit 2%

Vraag je hiernaar?

 public class VariantDate {
    public int day;
    public int month;
    public int year;
    public VariantDate(int day) : this(day, 1) {}
    public VariantDate(int day, int month) : this(day, month,1900){}
    public VariantDate(int day, int month, int year){
    this.day=day;
    this.month=month;
    this.year=year;
    }
}

Antwoord 7

Al die antwoorden zijn goed, maar ik zou graag een opmerking willen toevoegen over constructors met wat complexere initialisaties.

class SomeClass {
    private int StringLength;
    SomeClass(string x) {
         // this is the logic that shall be executed for all constructors.
         // you dont want to duplicate it.
         StringLength = x.Length;
    }
    SomeClass(int a, int b): this(TransformToString(a, b)) {
    }
    private static string TransformToString(int a, int b) {
         var c = a + b;
         return $"{a} + {b} = {c}";
    }
}

Hoewel dit voorbeeld net zo goed kan worden opgelost zonder deze statische functie, maakt de statische functie complexere logica mogelijk, of zelfs het aanroepen van methoden van ergens anders.


Antwoord 8

Ik hoop dat het volgende voorbeeld enig licht werpt op constructor chaining.
mijn use-case hier bijvoorbeeld, u verwacht dat de gebruiker een map doorgeeft aan uw
constructor, gebruiker weet niet welke map hij moet doorgeven en besluit te laten
U wijst de standaardmap toe. U stapt op en wijs een standaardmap toe die u denkt
zal werken.

BTW, ik heb Linqpad voor dit voorbeeld gebruikt voor het geval je je afvraagt ​​wat * .dump () is.
Cheers

void Main()
{
    CtorChaining ctorNoparam = new CtorChaining();
    ctorNoparam.Dump();
    //Result --> BaseDir C:\Program Files (x86)\Default\ 
    CtorChaining ctorOneparam = new CtorChaining("c:\\customDir");
    ctorOneparam.Dump();    
    //Result --> BaseDir c:\customDir 
}
public class CtorChaining
{
    public string BaseDir;
    public static string DefaultDir = @"C:\Program Files (x86)\Default\";
    public CtorChaining(): this(null) {}
    public CtorChaining(string baseDir): this(baseDir, DefaultDir){}
    public CtorChaining(string baseDir, string defaultDir)
    {
        //if baseDir == null, this.BaseDir = @"C:\Program Files (x86)\Default\"
        this.BaseDir = baseDir ?? defaultDir;
    }
}

Antwoord 9

Er is een ander belangrijk punt in de constructorchanking: bestelling.
Waarom?
Laten we zeggen dat je een object hebt dat wordt geconstrueerd bij runtime door een raamwerk dat verwacht dat het de standaardconstructeur is. Als u in staat wilt zijn om waarden in te dienen, terwijl u nog steeds het vermogen hebt om constructeur te laten passeren, is dit als u wilt, dit is uiterst nuttig.

Ik kan bijvoorbeeld een steunvariabele hebben die wordt ingesteld op een standaardwaarde door mijn standaardconstructeur, maar heeft de mogelijkheid om te worden overschreven.

public class MyClass
{
  private IDependency _myDependency;
  MyClass(){ _myDependency = new DefaultDependency(); }
  MYClass(IMyDependency dependency) : this() {
    _myDependency = dependency; //now our dependency object replaces the defaultDependency
  }
}

Other episodes