สร้างคอนสตรัคเตอร์ของคลาสและสร้างอินสแตนซ์ออบเจ็กต์

เสร็จสมบูรณ์เมื่อ

ข้อกําหนดคลาสจะรวมตัวสร้างที่ใช้ในการเตรียมใช้งานออบเจ็กต์ใหม่ (อินสแตนซ์ของคลาส)

คอนสตรัคเตอร์ของคลาส

คอนสตรักเตอร์ของคลาส เป็นวิธีการที่มีชื่อเดียวกันกับชนิด (วิธีการของคอนสตรักเตอร์ใช้ชื่อเดียวกันกับคลาส)

มีคอนสตรัคเตอร์ของคลาสสองชนิด ได้แก่

  • คอนสตรัคเตอร์ของอินสแตนซ์ คอนสตรัคเตอร์อินสแตนซ์จะถูกใช้เพื่อสร้างและเริ่มต้นตัวแปรฟิลด์อินสแตนซ์ใดๆ เมื่อสร้างออบเจ็กต์
  • คอนสตรัคเตอร์แบบคงที่ คอนสตรัคเตอร์แบบคงที่จะถูกใช้เพื่อเริ่มต้นข้อมูลแบบคงที่หรือเพื่อดําเนินการบางอย่างที่จําเป็นต้องดําเนินการเพียงครั้งเดียว คอนสตรัคเตอร์แบบคงที่จะถูกเรียกใช้โดยอัตโนมัติก่อนที่จะมีการสร้างอินสแตนซ์แรก หรือมีการอ้างอิงสมาชิกแบบคงที่

คอนสตรัคเตอร์ของคลาสคือ คอนสตรัคเตอร์ของอินสแตนซ์ตามค่าเริ่มต้น

ไวยากรณ์คอนสตรักเตอร์ของอินสแตนซ์

มีการประกาศคอนสตรักเตอร์อินสแตนซ์โดยใช้ชื่อเดียวกันกับคลาส และไม่มีชนิดการส่งกลับ ลายเซ็นวิธีการของคอนสตรักเตอร์สามารถรวมตัวปรับเปลี่ยนการเข้าถึงที่เลือกได้ ชื่อวิธีการ และรายการพารามิเตอร์ ลายเซ็นวิธีการของคอนสตรักเตอร์ไม่มีชนิดการส่งคืน

ตัวอย่างต่อไปนี้แสดงคอนสตรักเตอร์อย่างง่ายสําหรับคลาสที่มีชื่อว่า Person:


public class Person
{
    public Person()
    {
        // Field initialization and constructor logic goes here.

    }

    // Remaining implementation of Person class.
}

คลาสสามารถมีคอนสตรักเตอร์ได้มากกว่าหนึ่งรายการ เมื่อคลาสมีคอนสตรักเตอร์มากกว่าหนึ่งรายการ คอนสตรักเตอร์มักจะใช้อาร์กิวเมนต์ที่แตกต่างกัน

ตัวอย่างต่อไปนี้แสดงคลาสที่มีชื่อ Person ที่มีคอนสตรัคเตอร์สองตัว


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.
}

สร้างอินสแตนซ์ของออบเจ็กต์โดยใช้คอนสตรัคเตอร์ของคลาส

เมื่อมีการสร้างอินสแตนซ์ของออบเจ็กต์โดยใช้คําสําคัญ new รันไทม์ .NET จะเรียกใช้คอนสตรักเตอร์ของอินสแตนซ์ที่เกี่ยวข้องในข้อกําหนดของคลาส และจัดสรรหน่วยความจําสําหรับออบเจ็กต์

ในส่วนย่อยของโค้ดต่อไปนี้ คลาส Person จะกําหนดคอนสตรักเตอร์ของอินสแตนซ์แบบง่าย คลาส Program มีวิธีการ Main ที่ใช้ตัวดําเนินการ new เพื่อสร้างอินสแตนซ์ของ Person ที่ชื่อว่า person1 รันไทม์จะเรียกใช้คอนสตรักเตอร์ Person ทันทีหลังจากที่มีการจัดสรรหน่วยความจําสําหรับวัตถุใหม่


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();
    }
}

คอนสตรัคเตอร์ที่มี และ ไม่มีพารามิเตอร์

คอนสตรักเตอร์ที่ไม่ใช้พารามิเตอร์เรียกว่า คอนสตรักเตอร์แบบไม่มีพารามิเตอร์ รันไทม์จะเรียกใช้คอนสตรักเตอร์แบบไม่มีพารามิเตอร์เมื่อมีการสร้างอินสแตนซ์ของวัตถุโดยใช้ตัวดําเนินการ new และไม่มีอาร์กิวเมนต์ให้กับคอนสตรักเตอร์

โน้ต

เว้นแต่คลาสจะคงที่ คลาสที่ไม่มีคอนสตรักเตอร์จะได้รับคอนสตรักเตอร์แบบไม่มีพารามิเตอร์สาธารณะโดยคอมไพเลอร์ C# เพื่อเปิดใช้งานการสร้างอินสแตนซ์ของคลาส

คลาสมักจะกําหนดคอนสตรัคเตอร์ที่ใช้พารามิเตอร์ ต้องเรียกคอนสตราเตอร์ที่ใช้พารามิเตอร์โดยใช้ตัวดําเนินการ new หรือคําสั่งพื้นฐาน คลาสสามารถกําหนดคอนสตรัคเตอร์อย่างน้อยหนึ่งรายการ

ส่วนย่อยของโค้ดต่อไปนี้แสดงคลาสที่ชื่อ Person ที่มีคอนสตรัคเตอร์สามรายการ:


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);
    }
}

คลาสที่ไม่มีคอนสตรัคเตอร์

ถ้าคลาสไม่มีคอนสตรักเตอร์ของอินสแตนซ์ที่ชัดเจน C# มีคอนสตรักเตอร์แบบไม่มีพารามิเตอร์ที่คุณสามารถใช้เพื่อสร้างอินสแตนซ์ของคลาสนั้นตามตัวอย่างต่อไปนี้จะแสดง:


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
    }
}

คอนสตรักเตอร์นี้จะเริ่มต้นเขตข้อมูลอินสแตนซ์และคุณสมบัติตามตัวกําหนดค่าเริ่มต้นที่สอดคล้องกัน ถ้าเขตข้อมูลหรือคุณสมบัติไม่มีตัวกําหนดค่าเริ่มต้น ค่าของเขตข้อมูลจะถูกตั้งค่าเป็นค่าเริ่มต้นของชนิดของเขตข้อมูลหรือของคุณสมบัติ ถ้าคุณตรวจนับคอนสตรักเตอร์ของอินสแตนซ์อย่างน้อยหนึ่งตัวในคลาส C# จะไม่กําหนดคอนสตรักเตอร์แบบไม่มีพารามิเตอร์

เริ่มต้นข้อมูลคลาสโดยใช้พารามิเตอร์คอนสตรักเตอร์

พารามิเตอร์ที่ส่งผ่านไปยังคอนสตรักเตอร์จะอยู่ภายในเครื่องไปยังคอนสตรักเตอร์ พารามิเตอร์มักใช้เพื่อเริ่มต้นเขตข้อมูลของคลาส

ส่วนย่อยของโค้ดต่อไปนี้แสดงคลาสที่มีชื่อ Person ด้วยคอนสตรัคเตอร์ที่มีการเตรียมใช้งานเขตข้อมูล personName และ 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}");
    }
}

ในตัวอย่างก่อนหน้านี้ คลาส Person จะถูกกําหนดด้วยคอนสตอร์มสามตัว คอนสตรักเตอร์แรกจะเริ่มต้นเขตข้อมูล personName และ personAge เพื่อ "unknown" คอนสตรักเตอร์ที่สองจะเริ่มต้นเขตข้อมูล personName เป็นค่าที่ส่งผ่านในพารามิเตอร์ name และเขตข้อมูล personAge เพื่อ "unknown" คอนสตรักเตอร์ที่สามจะเริ่มต้นเขตข้อมูล personName และ personAge ไปยังค่าที่ส่งผ่านในพารามิเตอร์ name และ age ตามลําดับ

เนื่องจากเขตข้อมูลเป็นสาธารณะ พวกเขาสามารถเข้าถึงได้โดยตรงจากวิธี Main เมื่อเรียกใช้โค้ด ผลลัพธ์ต่อไปนี้จะถูกสร้างขึ้น:


Person 1 Name: unknown Age: unknown
Person 2 Name: Jane Doe Age: unknown
Person 3 Name: John Doe Age: 30

ข้อกําหนดเนื้อความของนิพจน์

ถ้าคอนสตรักเตอร์สามารถใช้เป็นคําสั่งเดียวได้ คุณสามารถใช้ข้อกําหนดเนื้อความของนิพจน์ เพื่อกําหนดพารามิเตอร์ให้กับสมาชิกคลาสเมื่อมีการใช้คอนสตรักเตอร์

ตัวอย่างเช่น คอนสตรักเตอร์ต่อไปนี้จะเริ่มต้นเขตข้อมูล modelName ด้วยค่าที่ส่งผ่านไปยังพารามิเตอร์ model:


public class Car
{
    public string modelName;

    public Car(string model) => modelName = model;
    
}

คลาส Car มีเขตข้อมูลสาธารณะเดียว modelNameซึ่งเป็นชนิด string เขตข้อมูล modelName มีวัตถุประสงค์เพื่อจัดเก็บชื่อของรุ่นรถยนต์

คลาส Car ยังรวมถึงคอนสตรักเตอร์ที่ใช้พารามิเตอร์สตริงเดียวที่ชื่อว่า modelด้วย คอนสตรักเตอร์ใช้ข้อกําหนดเนื้อความของนิพจน์ (แสดงโดยไวยากรณ์ =>) เพื่อเริ่มต้นเขตข้อมูล modelName ด้วยค่าที่ส่งผ่านไปยังพารามิเตอร์ model ซึ่งหมายความว่าเมื่อมีการสร้างอินสแตนซ์วัตถุ Car ใหม่ เขตข้อมูล modelName จะถูกตั้งค่าเป็นค่าที่ระบุเป็นอาร์กิวเมนต์สําหรับคอนสตรักเตอร์

เนื่องจากคํา นิพจน์ บอกเป็นนัย ทางด้านขวาของตัวดําเนินการ => เป็นนิพจน์และไม่จํากัดเพียงคําสั่งการกําหนดอย่างง่าย นิพจน์ สามารถเป็นนิพจน์ C# ที่ถูกต้องใด ๆ ที่แสดงค่า

ส่วนย่อยของโค้ดต่อไปนี้สาธิตวิธีการใช้ข้อกําหนดเนื้อความของนิพจน์ที่ทําการคํานวณแบบง่าย:


public class Employee
{
    public int Salary;

    public Employee() { }

    public Employee(int annualSalary) => Salary = annualSalary;

    public Employee(int weeklySalary, int numberOfWeeks) => Salary = weeklySalary * numberOfWeeks;
}

ชั้นนี้สามารถสร้างโดยใช้คําสั่งใดคําสั่งหนึ่งต่อไปนี้:


Employee e1 = new Employee(30000);
Employee e2 = new Employee(500, 52);

คอนสตรัคเตอร์แบบคงที่

คอนสตรักเตอร์แบบคงที่ถูกใช้เพื่อเริ่มต้นข้อมูลแบบคงที่ใด ๆ หรือเพื่อดําเนินการเฉพาะที่จําเป็นต้องดําเนินการเพียงครั้งเดียว ซึ่งจะถูกเรียกใช้โดยอัตโนมัติก่อนที่จะมีการสร้างอินสแตนซ์แรก หรือมีการอ้างอิงสมาชิกแบบคงที่ คอนสตรักเตอร์แบบคงที่จะถูกเรียกมากที่สุดหนึ่งครั้ง

ส่วนย่อยของโค้ดต่อไปนี้แสดงคลาส Person ที่อัปเดตแล้ว ที่ใช้เขตข้อมูลแบบคงที่และคอนสตรักเตอร์แบบคงที่:


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();
    }
}

คลาส Person ที่อัปเดตแล้ว มีฟิลด์อินสแตนซ์สองฟิลด์ personName และ personAgeซึ่งทั้งสองคลาสเป็นชนิด string เขตข้อมูลเหล่านี้จะจัดเก็บชื่อและอายุของบุคคลตามลําดับ

คลาส ยังกําหนดเขตข้อมูลแบบคงที่สองเขต defaultName และ defaultAgeนอกจากนี้ยังกําหนดชนิด stringด้วย เขตข้อมูลแบบคงที่จะถูกแชร์ระหว่างอินสแตนซ์ทั้งหมดของคลาส และถูกเตรียมใช้งานเพียงครั้งเดียว ในกรณีนี้ จะใช้เขตข้อมูลแบบคงที่เพื่อให้ค่าเริ่มต้นสําหรับเขตข้อมูล personName และ personAge

คอนสตรักเตอร์แบบคงที่ static Person() มีหน้าที่รับผิดชอบในการเตรียมใช้งานเขตข้อมูลแบบคงที่ ตั้งค่า defaultName เป็น "ไม่ทราบ" และ defaultAge เป็น "unknown" คอนสตรักเตอร์แบบคงที่จะถูกเรียกโดยอัตโนมัติก่อนที่จะมีการสร้างอินสแตนซ์ใด ๆ ของคลาสหรือมีการเข้าถึงสมาชิกแบบคงที่

คลาส Person ประกอบด้วยคอนสตรัคเตอร์ของอินสแตนซ์สามรายการ:

คอนสตรักเตอร์แบบไม่มีพารามิเตอร์ public Person() เริ่มต้นเขตข้อมูล personName และ personAge ด้วยค่าของเขตข้อมูลแบบคงที่ defaultName และ defaultAge ซึ่งหมายความว่าหากไม่มีการระบุอาร์กิวเมนต์เมื่อสร้างออบเจ็กต์ Person ค่าเริ่มต้น "ไม่ทราบ" จะถูกใช้สําหรับทั้งชื่อและอายุ

คอนสตรักเตอร์ public Person(string name) ใช้พารามิเตอร์เดียว nameและเตรียมใช้งานเขตข้อมูล personName ด้วยค่านี้ เขตข้อมูล personAge ถูกเตรียมใช้งานด้วยค่าของเขตข้อมูลแบบคงที่ defaultAge คอนสตรักเตอร์นี้อนุญาตให้มีการสร้างวัตถุ Person ด้วยชื่อที่ระบุในขณะที่ใช้อายุเริ่มต้น

คอนสตรักเตอร์ public Person(string name, int age) ใช้สองพารามิเตอร์ name และ age ซึ่งจะเริ่มต้นเขตข้อมูล personName ด้วยค่าของพารามิเตอร์ name และเขตข้อมูล personAge ที่มีการแสดงสตริงของพารามิเตอร์อายุ คอนสตรักเตอร์นี้อนุญาตให้มีการสร้างวัตถุ Person ที่มีทั้ง name และ ageที่ระบุ

คุณสมบัติของคอนสตรัคเตอร์แบบคงที่

คอนสตรัคเตอร์แบบคงที่มีคุณสมบัติต่อไปนี้:

  • คอนสตรักเตอร์แบบคงที่ไม่ใช้ตัวปรับเปลี่ยนการเข้าถึงหรือมีพารามิเตอร์

  • คลาสสามารถมีคอนสตรักเตอร์แบบคงที่ได้เพียงหนึ่งคอนสตรักเตอร์เท่านั้น

  • คอนสตรัคเตอร์แบบคงที่ไม่สามารถสืบทอดหรือโอเวอร์โหลดได้

  • ไม่สามารถเรียกคอนสตรักเตอร์แบบคงที่ได้โดยตรงและเป็นเพียงการเรียกใช้โดยรันไทม์ภาษาทั่วไป (CLR) เท่านั้น ซึ่งจะถูกเรียกใช้โดยอัตโนมัติ

  • ผู้ใช้ไม่มีการควบคุมเมื่อมีการดําเนินการคอนสตรักเตอร์แบบคงที่ในโปรแกรม

  • คอนสตรักเตอร์แบบคงที่จะถูกเรียกโดยอัตโนมัติ ซึ่งจะเตรียมใช้งานคลาสก่อนที่จะสร้างอินสแตนซ์แรก หรือมีการอ้างอิงสมาชิกแบบคงที่ที่ประกาศในคลาสนั้น (ไม่ใช่คลาสพื้นฐาน) คอนสตรักเตอร์แบบคงที่จะทํางานก่อนคอนสตรักเตอร์ของอินสแตนซ์ ถ้าตัวกําหนดค่าเริ่มต้นของตัวแปรเขตข้อมูลแบบคงที่ปรากฏอยู่ในคลาส ของคอนสตรักเตอร์แบบคงที่ ตัวกําหนดค่าเหล่านี้จะทํางานตามลําดับข้อความที่ปรากฏในการประกาศคลาส ตัวกําหนดค่าเริ่มต้นจะทํางานทันทีก่อนคอนสตรักเตอร์แบบคงที่

  • ถ้าคุณไม่มีคอนสตรักเตอร์แบบคงที่เพื่อเตรียมใช้งานเขตข้อมูลแบบคงที่ เขตข้อมูลแบบคงที่ทั้งหมดจะถูกเตรียมใช้งานเป็นค่าเริ่มต้น

  • ถ้าคอนสตรักเตอร์แบบคงที่แสดงข้อยกเว้น รันไทม์จะไม่เรียกใช้เป็นครั้งที่สอง และชนิด จะยังคงไม่มีเริ่มต้นสําหรับอายุการใช้งานของโดเมนแอปพลิเคชัน โดยทั่วไปแล้ว ข้อยกเว้นของ TypeInitializationException จะเกิดขึ้นเมื่อคอนสตรักเตอร์แบบคงที่ไม่สามารถสร้างอินสแตนซ์ชนิดหรือสําหรับข้อยกเว้นที่ไม่สามารถจัดการได้ที่เกิดขึ้นภายในคอนสตรักเตอร์แบบคงที่ สําหรับคอนสตรัคเตอร์แบบคงที่ที่ไม่ได้กําหนดไว้อย่างชัดเจนในโค้ดต้นฉบับ การแก้ไขปัญหาอาจจําเป็นต้องตรวจสอบรหัสภาษาระดับกลาง (IL)

  • การปรากฏของคอนสตรักเตอร์แบบคงที่จะป้องกันการเพิ่มแอตทริบิวต์ประเภท BeforeFieldInit ซึ่งจํากัดการปรับรันไทม์ให้เหมาะสม

  • สามารถกําหนดเขตข้อมูลที่ประกาศเป็น static readonly เป็นส่วนหนึ่งของการประกาศหรือในคอนสตรักเตอร์แบบคงที่เท่านั้น เมื่อไม่จําเป็นต้องใช้คอนสตรักเตอร์แบบคงที่อย่างชัดเจน ให้เริ่มต้นเขตข้อมูลแบบคงที่ในการประกาศแทนที่จะผ่านคอนสตรักเตอร์แบบคงที่เพื่อการปรับให้เหมาะสมรันไทม์ที่ดีขึ้น

  • รันไทม์จะเรียกใช้คอนสตรักเตอร์แบบคงที่ไม่เกินหนึ่งครั้งในโดเมนแอปพลิเคชันเดียว การเรียกใช้นั้นจะทําในภูมิภาคที่ล็อกไว้โดยยึดตามชนิดเฉพาะของคลาส ไม่จําเป็นต้องใช้กลไกล็อคพิเศษในเนื้อความของคอนสตรักเตอร์แบบคงที่

โน้ต

แม้ว่าจะไม่สามารถเข้าถึงได้โดยตรง การมีคอนสตรักเตอร์แบบคงที่ที่ชัดเจนควรได้รับการจัดทําเอกสารเพื่อช่วยแก้ไขปัญหาข้อยกเว้นการเตรียมใช้งาน