Opret klassekonstruktører, og instantier objekter
Ud over klasseegenskaber og -metoder omfatter klassedefinitioner konstruktører, der bruges til at initialisere nye objekter (klasseforekomster).
Klassekonstruktører
En klassekonstruktør er en metode med samme navn som dens type (konstruktørmetoder bruger det samme navn som klassen).
Der er to typer klassekonstruktører:
- Forekomstkonstruktører. Forekomstkonstruktører bruges til at oprette og initialisere alle feltvariabler for forekomster, når der oprettes et objekt.
- Statiske konstruktører. Statiske konstruktører bruges til at initialisere statiske data eller til at udføre en bestemt handling, der kun skal udføres én gang. Statiske konstruktører kaldes automatisk, før den første forekomst oprettes, eller der refereres til statiske medlemmer.
Klassekonstruktører er som standard forekomstkonstruktører.
Syntaks for forekomstkonstruktør
En forekomstkonstruktør erklæres med samme navn som klassen og indeholder ikke en returtype. Konstruktørens metodesignatur kan indeholde en valgfri adgangsændring, metodenavnet og dens parameterliste. En konstruktørs metodesignaturer indeholder ikke en returtype.
I følgende eksempel vises en simpel konstruktør for en klasse med navnet Person:
public class Person
{
public Person()
{
// Field initialization and constructor logic goes here.
}
// Remaining implementation of Person class.
}
Klasser kan have mere end én konstruktør. Når en klasse har mere end én konstruktør, tager konstruktørerne normalt forskellige argumenter.
I følgende eksempel vises en klasse med navnet Person med to konstruktører.
public class Person
{
public Person()
{
// Field initialization and constructor logic goes here.
string name = "John Doe";
Console.WriteLine($"Person created: {name}");
}
public Person(string fName, string lName)
{
string name = fName + " " + lName;
Console.WriteLine($"Person created: {name}");
}
// Remaining implementation of Person class.
}
Instantier objekter ved hjælp af klassekonstruktører
Når et objekt instantieres ved hjælp af nøgleordet new, kalder .NET-kørslen den tilknyttede forekomstkonstruktør i klassedefinitionen og tildeler hukommelse til objektet.
I følgende kodestykke definerer klassen Person en enkel forekomstkonstruktør. Klassen Program indeholder en Main metode, der bruger operatoren new til at oprette en forekomst af Person med navnet person1. Runtime aktiverer den Person konstruktør, umiddelbart efter at der er allokeret hukommelse til det nye objekt.
public class Person
{
public Person()
{
// Field initialization and constructor logic goes here.
}
}
static class Program
{
// the Main method is the entry point of the program.
static void Main()
{
Person person1 = new Person();
}
}
Konstruktører med og uden parametre
En konstruktør, der ikke tager nogen parametre, kaldes en konstruktør uden parametre. Runtime aktiverer konstruktøren uden parametre, når et objekt instantieres ved hjælp af operatoren new, og der ikke er angivet nogen argumenter for konstruktøren.
Seddel
Medmindre klassen er statisk, får klasser uden konstruktører en offentlig konstruktør uden parametre af C#-compileren for at aktivere instantiering af klassen.
Klasser definerer ofte konstruktører, der tager parametre. Konstruktører, der tager parametre, skal kaldes ved hjælp af operatoren new eller en basissætning. Klasser kan definere en eller flere konstruktører.
Følgende kodestykke viser en klasse med navnet Person med tre konstruktører:
public class Person
{
public Person()
{
// Field initialization and constructor logic goes here.
Console.WriteLine("An instance of the Person class is being instantiated without name or age parameters.");
}
public Person(string name)
{
// Field initialization and constructor logic goes here.
Console.WriteLine($"An instance of the Person class is being instantiated using a name ({name}) parameter.");
}
public Person(string name, int age)
{
// Field initialization and constructor logic goes here.
Console.WriteLine($"An instance of the Person class is being instantiated using name ({name}) and age ({age}) parameters.");
}
}
static class Program
{
// the Main method is the entry point of the program.
static void Main()
{
Person person1 = new Person();
Person person2 = new Person("Jane Doe");
Person person3 = new Person("John Doe", 30);
}
}
Klasser uden konstruktører
Hvis en klasse ikke har nogen eksplicitte forekomstkonstruktører, leverer C# en konstruktør uden parametre, som du kan bruge til at instantiere en forekomst af klassen, som vist i følgende eksempel:
public class Person
{
public int age;
public string name = "unknown";
}
class Example
{
static void Main()
{
var person = new Person();
Console.WriteLine($"Name: {person.name}, Age: {person.age}");
// Output: Name: unknown, Age: 0
}
}
Denne konstruktør initialiserer forekomstfelter og egenskaber i henhold til de tilsvarende initialiseringer. Hvis et felt eller en egenskab ikke har nogen initialiseringsfunktion, angives dets værdi til standardværdien for feltets eller egenskabens type. Hvis du deklarerer mindst én forekomstkonstruktør i en klasse, indeholder C# ikke en konstruktør uden parametre.
Initialiser klassedata ved hjælp af konstruktørparametre
De parametre, der overføres til en konstruktør, er lokale for konstruktøren. Parametre bruges ofte til at initialisere datafelterne i en klasse.
Følgende kodestykke viser en klasse med navnet Person med konstruktører, der initialiserer felterne personName og personAge:
public class Person
{
public string personName;
public string personAge;
public Person()
{
// Field initialization and constructor logic goes here.
personName = "unknown";
personAge = "unknown";
}
public Person(string name)
{
// Field initialization and constructor logic goes here.
personName = name;
personAge = "unknown";
}
public Person(string name, int age)
{
// Field initialization and constructor logic goes here.
personName = name;
personAge = age.ToString();
}
}
static class Program
{
// the Main method is the entry point of the program.
static void Main()
{
Person person1 = new Person();
Person person2 = new Person("Jane Doe");
Person person3 = new Person("John Doe", 30);
Console.WriteLine($"Person 1 Name: {person1.personName} Age: {person1.personAge}");
Console.WriteLine($"Person 2 Name: {person2.personName} Age: {person2.personAge}");
Console.WriteLine($"Person 3 Name: {person3.personName} Age: {person3.personAge}");
}
}
I det foregående eksempel er klassen Person defineret med tre konstruktører. Den første konstruktør initialiserer felterne personName og personAge til "unknown". Den anden konstruktør initialiserer feltet personName til den værdi, der overføres i parameteren name, og feltet personAge til "unknown". Den tredje konstruktør initialiserer felterne personName og personAge til de værdier, der overføres i parametrene name og age.
Da felterne er offentlige, kan du få adgang til dem direkte fra metoden Main. Når koden kører, genereres følgende output:
Person 1 Name: unknown Age: unknown
Person 2 Name: Jane Doe Age: unknown
Person 3 Name: John Doe Age: 30
Brødtekstdefinitioner for udtryk
Hvis en konstruktør kan implementeres som en enkelt sætning, kan du bruge en udtryksbrødtekstdefinition til at tildele en parameter til et klassemedlem, når konstruktøren implementeres.
Følgende konstruktør initialiserer f.eks. feltet modelName med den værdi, der overføres til parameteren model:
public class Car
{
public string modelName;
public Car(string model) => modelName = model;
}
Klassen Car har et enkelt offentligt felt, modelName, som er af typen string. Feltet modelName er beregnet til at gemme navnet på bilmodellen.
Klassen Car indeholder også en konstruktør, der tager en enkelt strengparameter med navnet model. Konstruktøren bruger en brødtekstdefinition for udtryk (angivet af =>-syntaksen) til at initialisere feltet modelName med den værdi, der overføres til parameteren model. Det betyder, at når et nyt Car-objekt instantieres, angives feltet modelName til den værdi, der er angivet som et argument for konstruktøren.
Som udtrykket udtryk antyder, er højre side af operatoren => et udtryk og er ikke begrænset til en simpel tildelingssætning. Udtrykket kan være et hvilket som helst gyldigt C#-udtryk, der returnerer en værdi.
Følgende kodestykke viser, hvordan du implementerer en brødtekstdefinition for et udtryk, der udfører en simpel beregning:
public class Employee
{
public int Salary;
public Employee() { }
public Employee(int annualSalary) => Salary = annualSalary;
public Employee(int weeklySalary, int numberOfWeeks) => Salary = weeklySalary * numberOfWeeks;
}
Denne klasse kan oprettes ved hjælp af et af følgende sætninger:
Employee e1 = new Employee(30000);
Employee e2 = new Employee(500, 52);
Statiske konstruktører
En statisk konstruktør bruges til at initialisere statiske data eller til at udføre en bestemt handling, der kun skal udføres én gang. Den kaldes automatisk, før den første forekomst oprettes, eller der refereres til statiske medlemmer. En statisk konstruktør kaldes højst én gang.
Følgende kodestykke viser en opdateret version af klassen Person, der implementerer statiske felter og en statisk konstruktør:
public class Person
{
public string personName;
public string personAge;
// Static field
public static string defaultName;
public static string defaultAge;
// Static constructor
static Person()
{
// Static field initialization
defaultName = "unknown";
defaultAge = "unknown";
}
public Person()
{
// Field initialization and constructor logic goes here.
personName = defaultName;
personAge = defaultAge;
}
public Person(string name)
{
// Field initialization and constructor logic goes here.
personName = name;
personAge = defaultAge;
}
public Person(string name, int age)
{
// Field initialization and constructor logic goes here.
personName = name;
personAge = age.ToString();
}
}
Den opdaterede Person-klasse indeholder to forekomstfelter, personName og personAge, som begge er af typen string. I disse felter gemmes henholdsvis en persons navn og alder.
Klassen definerer også to statiske felter, defaultName og defaultAge, også af typen string. Statiske felter deles mellem alle forekomster af klassen og initialiseres kun én gang. I dette tilfælde bruges de statiske felter til at angive standardværdier for felterne personName og personAge.
Den statiske konstruktør static Person() er ansvarlig for initialisering af de statiske felter. Den angiver defaultName til "ukendt" og defaultAge til "unknown". Den statiske konstruktør kaldes automatisk, før der oprettes nogen forekomster af klassen, eller der åbnes statiske medlemmer.
Klassen Person indeholder tre forekomstkonstruktører:
Den parameterløse konstruktør public Person() initialiserer felterne personName og personAge med værdierne for de statiske felter defaultName og defaultAge. Det betyder, at hvis der ikke angives nogen argumenter, når du opretter et Person objekt, bruges standardværdierne "ukendt" til både navn og alder.
Konstruktøren public Person(string name) tager en enkelt parameter nameog initialiserer feltet personName med denne værdi. Feltet personAge initialiseres med værdien af det statiske felt defaultAge. Denne konstruktør gør det muligt at oprette et Person objekt med et angivet navn, mens standardalderen bruges.
Konstruktøren public Person(string name, int age) bruger to parametre, name og age. Det initialiserer feltet personName med værdien af parameteren name og feltet personAge med strengrepræsentationen af aldersparameteren. Denne konstruktør gør det muligt at oprette et Person objekt med både en angivet name og age.
Egenskaber for statiske konstruktører
Statiske konstruktører har følgende egenskaber:
En statisk konstruktør tager ikke adgangsændring eller har parametre.
En klasse kan kun have én statisk konstruktør.
Statiske konstruktører kan ikke nedarves eller overbelastes.
En statisk konstruktør kan ikke kaldes direkte og er kun beregnet til at blive kaldt af CLR (Common Language Runtime). Den aktiveres automatisk.
Brugeren har ingen kontrol over, hvornår den statiske konstruktør udføres i programmet.
En statisk konstruktør kaldes automatisk. Den initialiserer klassen, før den første forekomst oprettes, eller der refereres til statiske medlemmer, der er erklæret i den pågældende klasse (ikke dens basisklasser). En statisk konstruktør kører før en forekomstkonstruktør. Hvis initialiseringsfunktionen for variablen statiske felter findes i klassen for den statiske konstruktør, kører de i den tekstrækkefølge, de vises i i klasseerklæringen. Initialiseringsfunktionen kører umiddelbart før den statiske konstruktør.
Hvis du ikke angiver en statisk konstruktør til initialisering af statiske felter, initialiseres alle statiske felter til standardværdien.
Hvis en statisk konstruktør udløser en undtagelse, aktiverer kørselstidspunktet den ikke endnu en gang, og typen forbliver ikke initialiseret i hele programdomænets levetid. Normalt udløses der en
TypeInitializationExceptionundtagelse, når en statisk konstruktør ikke kan instantiere en type, eller hvis der opstår en ubehandlet undtagelse i en statisk konstruktør. For statiske konstruktører, der ikke eksplicit er defineret i kildekoden, kan fejlfinding kræve inspektion af den mellemliggende sprogkode (IL).Tilstedeværelsen af en statisk konstruktør forhindrer tilføjelsen af attributten
BeforeFieldInittype. Dette begrænser kørselsoptimering.Et felt, der er erklæret som
static readonly, kan kun tildeles som en del af dets erklæring eller i en statisk konstruktør. Når der ikke kræves en eksplicit statisk konstruktør, skal du initialisere statiske felter ved deklaration i stedet for via en statisk konstruktør for at få bedre optimering af kørsel.Runtime kalder ikke en statisk konstruktør mere end én gang i et enkelt programdomæne. Dette kald foretages i et låst område baseret på klassens specifikke type. Der kræves ingen ekstra låsemekanismer i en statisk konstruktørs brødtekst.
Seddel
Selvom den ikke er direkte tilgængelig, skal tilstedeværelsen af en eksplicit statisk konstruktør dokumenteres for at hjælpe med fejlfinding af initialiseringsundtagelser.