Skapa klasskonstruktorer och instansiera objekt
Förutom klassegenskaper och -metoder omfattar klassdefinitioner konstruktorer som används för att initiera nya objekt (klassinstanser).
Klasskonstruktorer
En klasskonstruktor är en metod med samma namn som dess typ (konstruktormetoder använder samma namn som klassen).
Det finns två typer av klasskonstruktorer:
- Instanskonstruktorer. Instanskonstruktorer används för att skapa och initiera instansfältvariabler när ett objekt skapas.
- Statiska konstruktorer. Statiska konstruktorer används för att initiera statiska data eller för att utföra en viss åtgärd som bara behöver utföras en gång. Statiska konstruktorer anropas automatiskt innan den första instansen skapas eller om några statiska medlemmar refereras till.
Klasskonstruktorer är instanskonstruktorer som standard.
Instanskonstruktorsyntax
En instanskonstruktor deklareras med samma namn som klassen och innehåller ingen returtyp. Konstruktorns metodsignatur kan innehålla en valfri åtkomstmodifierare, metodnamnet och dess parameterlista. En konstruktors metodsignaturer innehåller ingen returtyp.
I följande exempel visas en enkel konstruktor för en klass med namnet Person:
public class Person
{
public Person()
{
// Field initialization and constructor logic goes here.
}
// Remaining implementation of Person class.
}
Klasser kan ha fler än en konstruktor. När en klass har fler än en konstruktor tar konstruktorerna vanligtvis olika argument.
I följande exempel visas en klass med namnet Person med två konstruktorer.
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.
}
Instansiera objekt med hjälp av klasskonstruktorer
När ett objekt instansieras med nyckelordet new anropar .NET-körningen den associerade instanskonstruktorn i klassdefinitionen och allokerar minne för objektet.
I följande kodfragment definierar klassen Person en enkel instanskonstruktor. Klassen Program innehåller en Main-metod som använder operatorn new för att skapa en instans av Person med namnet person1. Körningen anropar Person konstruktorn omedelbart efter att minnet har allokerats för det nya objektet.
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();
}
}
Konstruktorer med och utan parametrar
En konstruktor som inte tar några parametrar kallas för en parameterlös konstruktor. Körningen anropar den parameterlösa konstruktorn när ett objekt instansieras med operatorn new och inga argument anges till konstruktorn.
Not
Om inte klassen är statisk får klasser utan konstruktorer en offentlig parameterlös konstruktor av C#-kompilatorn för att aktivera klassinstansiering.
Klasser definierar ofta konstruktorer som tar parametrar. Konstruktorer som tar parametrar måste anropas med operatorn new eller en basuttryck. Klasser kan definiera en eller flera konstruktorer.
Följande kodfragment visar en klass med namnet Person med tre konstruktorer:
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 utan konstruktorer
Om en klass inte har några explicita instanskonstruktorer tillhandahåller C# en parameterlös konstruktor som du kan använda för att instansiera en instans av den klassen, som följande exempel visar:
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
}
}
Den här konstruktorn initierar instansfält och egenskaper enligt motsvarande initialiserare. Om ett fält eller en egenskap inte har någon initiering anges dess värde till standardvärdet för fältets eller egenskapens typ. Om du deklarerar minst en instanskonstruktor i en klass tillhandahåller C# ingen parameterlös konstruktor.
Initiera klassdata med hjälp av konstruktorparametrar
Parametrarna som skickas till en konstruktor är lokala för konstruktorn. Parametrar används ofta för att initiera datafälten i en klass.
Följande kodfragment visar en klass med namnet Person med konstruktorer som initierar fälten personName och 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 föregående exempel definieras klassen Person med tre konstruktorer. Den första konstruktorn initierar fälten personName och personAge till "unknown". Den andra konstruktorn initierar fältet personName till värdet i parametern name och fältet personAge till "unknown". Den tredje konstruktorn initierar fälten personName och personAge till de värden som skickas i parametrarna name respektive age.
Eftersom fälten är offentliga kan de nås direkt från metoden Main. När koden körs genereras följande utdata:
Person 1 Name: unknown Age: unknown
Person 2 Name: Jane Doe Age: unknown
Person 3 Name: John Doe Age: 30
Uttryckstextdefinitioner
Om en konstruktor kan implementeras som en enda instruktion kan du använda en uttryckstextdefinition för att tilldela en parameter till en klassmedlem när konstruktorn implementeras.
Följande konstruktor initierar till exempel fältet modelName med värdet som skickas till parametern model:
public class Car
{
public string modelName;
public Car(string model) => modelName = model;
}
Klassen Car har ett enda offentligt fält, modelName, som är av typen string. Fältet modelName är avsett att lagra namnet på bilmodellen.
Klassen Car innehåller också en konstruktor som tar en enskild strängparameter med namnet model. Konstruktorn använder en uttryckstextdefinition (som anges av => syntax) för att initiera fältet modelName med värdet som skickas till parametern model. Det innebär att när ett nytt Car objekt instansieras anges fältet modelName till det värde som anges som ett argument för konstruktorn.
Som uttrycket antyder är operatorns => högra sida ett uttryck och är inte begränsat till en enkel tilldelningsinstruktion. Uttrycket kan vara valfritt giltigt C#-uttryck som returnerar ett värde.
Följande kodfragment visar hur du implementerar en uttryckstextdefinition som utför en enkel beräkning:
public class Employee
{
public int Salary;
public Employee() { }
public Employee(int annualSalary) => Salary = annualSalary;
public Employee(int weeklySalary, int numberOfWeeks) => Salary = weeklySalary * numberOfWeeks;
}
Den här klassen kan skapas med någon av följande instruktioner:
Employee e1 = new Employee(30000);
Employee e2 = new Employee(500, 52);
Statiska konstruktorer
En statisk konstruktor används för att initiera statiska data eller för att utföra en viss åtgärd som bara behöver utföras en gång. Den anropas automatiskt innan den första instansen skapas eller om några statiska medlemmar refereras till. En statisk konstruktor anropas högst en gång.
Följande kodfragment visar en uppdaterad version av klassen Person som implementerar statiska fält och en statisk konstruktor:
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 uppdaterade Person-klassen har två instansfält, personName och personAge, som båda är av typen string. De här fälten lagrar en persons namn respektive ålder.
Klassen definierar också två statiska fält, defaultName och defaultAge, även av typen string. Statiska fält delas mellan alla instanser av klassen och initieras bara en gång. I det här fallet används de statiska fälten för att ange standardvärden för fälten personName och personAge.
Den statiska konstruktorn static Person() ansvarar för att initiera de statiska fälten. Den anger defaultName till "okänd" och defaultAge till "unknown". Den statiska konstruktorn anropas automatiskt innan några instanser av klassen skapas eller några statiska medlemmar nås.
Klassen Person innehåller tre instanskonstruktorer:
Den parameterlösa konstruktorn public Person() initierar fälten personName och personAge med värdena för de statiska fälten defaultName och defaultAge. Det innebär att om inga argument anges när du skapar ett Person objekt används standardvärdena "okänd" för både namn och ålder.
Konstruktorn public Person(string name) tar en enda parameter, name, och initierar fältet personName med det här värdet. Fältet personAge initieras med värdet för det statiska fältet defaultAge. Med den här konstruktorn kan du skapa ett Person objekt med ett angivet namn när du använder standardåldern.
Konstruktorn public Person(string name, int age) tar två parametrar, name och age. Det initierar fältet personName med värdet för parametern name och fältet personAge med strängrepresentationen av åldersparametern. Med den här konstruktorn kan du skapa ett Person objekt med både en angiven name och age.
Egenskaper för statiska konstruktorer
Statiska konstruktorer har följande egenskaper:
En statisk konstruktor tar inte åtkomstmodifierare eller har parametrar.
En klass kan bara ha en statisk konstruktor.
Statiska konstruktorer kan inte ärvas eller överbelastas.
En statisk konstruktor kan inte anropas direkt och är endast avsedd att anropas av CLR (Common Language Runtime). Den anropas automatiskt.
Användaren har ingen kontroll över när den statiska konstruktorn körs i programmet.
En statisk konstruktor anropas automatiskt. Den initierar klassen innan den första instansen skapas eller om några statiska medlemmar som deklareras i den klassen (inte dess basklasser) refereras till. En statisk konstruktor körs före en instanskonstruktor. Om variabelinitierare för statiska fält finns i klassen för den statiska konstruktorn körs de i textordningen där de visas i klassdeklarationen. Initierarna körs omedelbart före den statiska konstruktorn.
Om du inte tillhandahåller en statisk konstruktor för att initiera statiska fält initieras alla statiska fält till standardvärdet.
Om en statisk konstruktor utlöser ett undantag anropar inte körningen det en andra gång och typen förblir oinitierad under programdomänens livslängd. Oftast utlöses ett
TypeInitializationExceptionundantag när en statisk konstruktor inte kan instansiera en typ eller för ett ohanterat undantag som inträffar inom en statisk konstruktor. För statiska konstruktorer som inte uttryckligen definieras i källkoden kan felsökning kräva kontroll av il-koden (intermediate language).Förekomsten av en statisk konstruktor förhindrar tillägg av attributet
BeforeFieldInittyp. Detta begränsar optimering vid körning.Ett fält som deklareras som
static readonlykan bara tilldelas som en del av deklarationen eller i en statisk konstruktor. När en explicit statisk konstruktor inte krävs initierar du statiska fält vid deklaration i stället för via en statisk konstruktor för bättre körningsoptimering.Körningen anropar en statisk konstruktor högst en gång i en enda programdomän. Det anropet görs i en låst region baserat på klassens specifika typ. Inga extra låsningsmekanismer behövs i kroppen av en statisk konstruktor.
Not
Även om det inte är direkt tillgängligt bör förekomsten av en explicit statisk konstruktor dokumenteras för att hjälpa till med felsökning av initieringsfel.