ตัวสร้างแบบคงที่ใช้เพื่อเริ่มต้นข้อมูลแบบคงที่หรือเพื่อดำเนินการเฉพาะที่ต้องทำเพียงครั้งเดียวเท่านั้น มันถูกเรียกโดยอัตโนมัติก่อนที่จะสร้างอินสแตนซ์แรกหรืออ้างอิงสมาชิกแบบคงที่
ตัวสร้างแบบคงที่มีประโยชน์เมื่อสร้างคลาส wrapper สำหรับโค้ดที่ไม่มีการจัดการ เมื่อตัวสร้างสามารถเรียกใช้เมธอด LoadLibrary ตัวสร้างแบบคงที่ยังเป็นสถานที่ที่สะดวกในการบังคับใช้การตรวจสอบรันไทม์กับพารามิเตอร์ประเภทที่ไม่สามารถตรวจสอบได้ในเวลารวบรวมผ่านข้อจำกัด
ตัวสร้างแบบคงที่มีคุณสมบัติดังต่อไปนี้ -
-
ตัวสร้างแบบคงที่ไม่รับตัวแก้ไขการเข้าถึงหรือมีพารามิเตอร์
-
คลาสหรือโครงสร้างสามารถมีคอนสตรัคเตอร์แบบคงที่ได้เพียงตัวเดียวเท่านั้น
-
ตัวสร้างแบบคงที่ไม่สามารถสืบทอดหรือโอเวอร์โหลดได้
-
คอนสตรัคเตอร์แบบสแตติกไม่สามารถเรียกได้โดยตรงและมีไว้เพื่อเรียกโดยรันไทม์ภาษาทั่วไป (CLR) เท่านั้น มันถูกเรียกใช้โดยอัตโนมัติ
-
ผู้ใช้ไม่มีการควบคุมเมื่อคอนสตรัคเตอร์แบบสแตติกถูกเรียกใช้งานในโปรแกรม
-
ตัวสร้างแบบคงที่ถูกเรียกโดยอัตโนมัติเพื่อเริ่มต้นคลาสก่อนที่จะสร้างอินสแตนซ์แรกหรืออ้างอิงสมาชิกแบบคงที่ staticconstructor จะทำงานก่อนตัวสร้างอินสแตนซ์ คอนสตรัคทอริสแบบคงที่ของประเภทถูกเรียกเมื่อเมธอดสแตติกที่กำหนดให้กับเหตุการณ์หรือผู้รับมอบสิทธิ์ถูกเรียกใช้และไม่ได้ถูกเรียกเมื่อถูกกำหนด หากมีตัวกำหนดค่าเริ่มต้นของตัวแปรฟิลด์สแตติกอยู่ในคลาสของคอนสตรัคเตอร์แบบคงที่ พวกเขาจะถูกดำเนินการในลำดับข้อความซึ่งจะปรากฏในการประกาศคลาสทันทีก่อนที่จะดำเนินการของคอนสตรัคคอนสตรัค
-
หากคุณไม่ได้จัดเตรียมคอนสตรัคเตอร์แบบคงที่เพื่อเริ่มต้นฟิลด์สแตติก ฟิลด์สแตติกทั้งหมดจะถูกเริ่มต้นเป็นค่าเริ่มต้นตามที่ระบุไว้ในค่าเริ่มต้นของประเภท C#
-
หากคอนสตรัคเตอร์แบบคงที่ส่งข้อยกเว้น รันไทม์จะไม่เรียกใช้เป็นครั้งที่สอง และประเภทจะยังไม่ได้กำหนดค่าเริ่มต้นตลอดอายุของโดเมนแอปพลิเคชันที่โปรแกรมของคุณกำลังทำงานอยู่ โดยทั่วไปแล้ว ข้อยกเว้น aTypeInitializationException จะเกิดขึ้นเมื่อคอนสตรัคเตอร์แบบคงที่ไม่สามารถสร้างอินสแตนซ์ของประเภทหรือสำหรับข้อยกเว้นที่ไม่สามารถจัดการได้ซึ่งเกิดขึ้นภายในคอนสตรัคเตอร์แบบ astatic สำหรับตัวสร้างสแตติกโดยนัยที่ไม่ได้กำหนดไว้อย่างชัดแจ้งในซอร์สโค้ด การแก้ไขปัญหาอาจต้องมีการตรวจสอบโค้ดภาษากลาง (IL)
-
การมีอยู่ของคอนสตรัคเตอร์แบบคงที่ช่วยป้องกันการเพิ่มแอตทริบิวต์ประเภท BeforeFieldInit สิ่งนี้จำกัดการเพิ่มประสิทธิภาพรันไทม์
-
ฟิลด์ที่ประกาศเป็นสแตติกอ่านอย่างเดียวอาจถูกกำหนดให้เป็นส่วนหนึ่งของการประกาศหรือในคอนสตรัคเตอร์แบบคงที่ เมื่อไม่ต้องการคอนสตรัคเตอร์แบบคงที่ที่ชัดเจน ให้เริ่มต้นฟิลด์สแตติกเมื่อมีการประกาศ แทนที่จะใช้คอนสตรัคเตอร์แบบคงที่เพื่อการเพิ่มประสิทธิภาพรันไทม์ที่ดีขึ้น
ตัวอย่าง
using System; namespace DemoApplication{ public class Program{ static void Main(string[] args){ Car user = new Car(); Car user1 = new Car(); Console.ReadLine(); } } public class Car{ static Car(){ Console.WriteLine("Static constructor called"); } public Car(){ Console.WriteLine("Default constructor called"); } } }
ผลลัพธ์
Static constructor called Default constructor called Default constructor called
ในตัวอย่างข้างต้น เราจะเห็นว่า static constructor ถูกเรียกเพียงครั้งเดียว
ตัวอย่าง
using System; using System.Threading; namespace DemoApplication{ public class Car{ protected static readonly DateTime globalStartTime; protected int RouteNumber { get; set; } static Car(){ globalStartTime = DateTime.Now; Console.WriteLine($"Static constructor called. Global start time: {globalStartTime.ToLongTimeString()}"); } public Car(int routeNum){ RouteNumber = routeNum; Console.WriteLine($"Car {RouteNumber} is created."); } public void Drive(){ TimeSpan elapsedTime = DateTime.Now - globalStartTime; Console.WriteLine($"Car {this.RouteNumber} is starting its route {elapsedTime.Milliseconds} minutes after global start time {globalStartTime.ToShortTimeString()}."); } } class TestCar{ static void Main(){ Car car1 = new Car(1); Car car2 = new Car(2); car1.Drive(); Thread.Sleep(25); car2.Drive(); Console.ReadLine(); } } }
ผลลัพธ์
Static constructor called. Global start time: 7:09:06 AM Car 1 is created. Car 2 is created. Car 1 is starting its route25 minutes after global start time7:09 AM. Car 2 is starting its route50 minutes after global start time7:09 AM.