ใช้คลาสโดยใช้คลาสบางส่วน

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

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

คลาสบางส่วน

มีหลายสถานการณ์เมื่อแยกข้อกําหนดคลาสเป็นที่ต้องการ:

  • การประกาศคลาสผ่านไฟล์แยกต่างหากช่วยให้ผู้เขียนโปรแกรมหลายคนทํางานได้ในเวลาเดียวกัน
  • คุณสามารถเพิ่มโค้ดลงในคลาสโดยไม่ต้องสร้างไฟล์ต้นฉบับที่มีแหล่งข้อมูลที่สร้างขึ้นโดยอัตโนมัติใหม่ Visual Studio ใช้วิธีนี้เมื่อสร้าง Windows Forms, Web service wrapper code และอื่น ๆ คุณสามารถสร้างโค้ดที่ใช้คลาสเหล่านี้ได้โดยไม่ต้องปรับเปลี่ยนไฟล์ที่สร้างขึ้นโดย Visual Studio
  • ตัวสร้างแหล่งที่มาสามารถสร้างฟังก์ชันการทํางานพิเศษในคลาส

เมื่อต้องการแยกข้อกําหนดคลาส ให้ใช้ตัวแก้ไขคําสําคัญบางส่วน ในทางปฏิบัติ แต่ละคลาสบางส่วนโดยทั่วไปจะถูกกําหนดในไฟล์แยกต่างหาก ทําให้ง่ายต่อการจัดการและขยายคลาสเมื่อเวลาผ่านไป

ตัวอย่าง Employee ต่อไปนี้สาธิตวิธีการแบ่งคลาสระหว่างสองไฟล์: Employee_Part1.cs และ Employee_Part2.cs


// This is in Employee_Part1.cs
public partial class Employee
{
    public void DoWork()
    {
        Console.WriteLine("Employee is working.");
    }
}


// This is in Employee_Part2.cs
public partial class Employee
{
    public void GoToLunch()
    {
        Console.WriteLine("Employee is at lunch.");
    }
}


//Main program demonstrating the Employee class usage
public class Program
{
    public static void Main()
    {
        Employee emp = new Employee();
        emp.DoWork();
        emp.GoToLunch();
    }
}

// Expected Output:
// Employee is working.
// Employee is at lunch.

คําสําคัญ partial ระบุว่าส่วนอื่น ๆ ของคลาสสามารถกําหนดได้ใน namespace ส่วนทั้งหมดต้องใช้คําสําคัญ partial ชิ้นส่วนทั้งหมดต้องพร้อมใช้งานในเวลาการคอมไพล์เพื่อรวมแบบฟอร์มชนิดสุดท้าย ส่วนทั้งหมดต้องมีความสามารถในการเข้าถึงเดียวกัน เช่น public, private, และอื่นๆ

หากส่วนใดถูกประกาศนามธรรม จะถือว่าเป็นนามธรรมทั้งชนิด หากส่วนใด ๆ ถูกประกาศปิดผนึกแล้วประเภททั้งหมดจะถือว่าเป็นซีล ถ้าส่วนใดส่วนหนึ่งประกาศชนิดฐาน ชนิดทั้งหมดจะสืบทอดคลาสนั้น

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

โน้ต

ตัวแก้ไข partial ไม่พร้อมใช้งานบนการมอบหมายหรือการแจกแจง

ตัวอย่างต่อไปนี้แสดงให้เห็นว่าชนิดที่ซ้อนกันสามารถเป็นบางส่วนได้ แม้ว่าชนิดที่อยู่ภายในจะไม่ได้ซ้อนกันบางส่วน


class Container
{
    partial class Nested
    {
        void Test() { }
    }

    partial class Nested
    {
        void Test2() { }
    }
}

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


[SerializableAttribute]
partial class Moon { }

[ObsoleteAttribute]
partial class Moon { }

ซึ่งเทียบเท่ากับการประกาศต่อไปนี้:


[SerializableAttribute]
[ObsoleteAttribute]
class Moon { }

ต่อไปนี้จะถูกผสานจากข้อกําหนดประเภทบางส่วนทั้งหมด:

  • ข้อคิดเห็น XML อย่างไรก็ตาม หากทั้งสองการประกาศของสมาชิกบางส่วนมีข้อคิดเห็น จะมีเพียงข้อคิดเห็นจากสมาชิกที่นําไปใช้เท่านั้น
  • อิน เทอร์ เฟซ
  • แอตทริบิวต์พารามิเตอร์ generic-type
  • แอตทริบิวต์คลาส
  • สมาชิก

ตัวอย่างเช่น พิจารณาประกาศต่อไปนี้:


partial class Earth : Planet, IRotate { }
partial class Earth : IRevolve { }

ซึ่งเทียบเท่ากับการประกาศต่อไปนี้:


class Earth : Planet, IRotate, IRevolve { }

ข้อจํากัดของข้อกําหนดของคลาสบางส่วน

มีหลายกฎที่ต้องปฏิบัติตามเมื่อคุณกําลังทํางานกับข้อกําหนดของคลาสบางส่วน:

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

    
    public partial class A { }
    //public class A { }  // Error, must also be marked partial
    
    
  • ตัวแก้ไขบางส่วนสามารถปรากฏได้ทันทีก่อนคลาสคําสําคัญ struct หรืออินเทอร์เฟซ

  • อนุญาตให้ใช้ชนิดบางส่วนที่ซ้อนกันในข้อกําหนดแบบบางส่วนตามที่แสดงในตัวอย่างต่อไปนี้:

    
    partial class ClassWithNestedClass
    {
        partial class NestedClass { }
    }
    
    partial class ClassWithNestedClass
    {
        partial class NestedClass { }
    }
    
    
  • ต้องกําหนดข้อกําหนดบางส่วนทั้งหมดที่มีไว้เพื่อเป็นส่วนหนึ่งของประเภทเดียวกันในแอสเซมบลีเดียวกันและโมดูลเดียวกัน (ไฟล์.exe หรือ .dll) ข้อกําหนดบางส่วนไม่สามารถครอบคลุมหลายมอดูลได้

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

  • คําสําคัญต่อไปนี้ในข้อกําหนดชนิดบางส่วนเป็นทางเลือก แต่ถ้ามีอยู่บนข้อกําหนดชนิดบางส่วนหนึ่งรายการ ต้องระบุแบบเดียวกันในข้อกําหนดบางส่วนอื่น ๆ สําหรับชนิดเดียวกัน:

    • สาธารณะ
    • ส่วนตัว
    • ป้องกัน
    • ภายใน
    • นามธรรม
    • ปิด
    • คลาสพื้นฐาน
    • ตัวปรับเปลี่ยนใหม่ (ส่วนที่ซ้อนกัน)
    • ข้อจํากัดทั่วไป

ใช้คลาสบางส่วน

ในตัวอย่างต่อไปนี้ มีการประกาศฟิลด์และคอนสตรักเตอร์ของคลาส Coords ในข้อกําหนดคลาสบางส่วนหนึ่งรายการ (Coords_Part1.cs) และมีการประกาศวิธีการ PrintCoords ในข้อกําหนดคลาสบางส่วนอื่น (Coords_Part2.cs) การแยกนี้แสดงให้เห็นว่าสามารถแบ่งคลาสบางส่วนในหลายไฟล์ได้อย่างไรเพื่อให้ง่ายต่อการบํารุงรักษา


// This is in Coords_Part1.cs
 public partial class Coords
 {
     private int x;
     private int y;

     public Coords(int x, int y)
     {
         this.x = x;
         this.y = y;
     }
 }

 // This is in Coords_Part2.cs
 public partial class Coords
 {
     public void PrintCoords()
     {
         Console.WriteLine("Coords: {0},{1}", x, y);
     }
 }

// Main program demonstrating the Coords class usage
 class TestCoords
 {
     static void Main()
     {
         Coords myCoords = new Coords(10, 15);
         myCoords.PrintCoords();

         // Keep the console window open in debug mode.
         Console.WriteLine("Press any key to exit.");
         Console.ReadKey();
     }
 }
 // Output: Coords: 10,15

สมาชิกบางส่วน

คลาสบางส่วนสามารถประกอบด้วยสมาชิกบางส่วนได้ ส่วนหนึ่งของคลาสมีลายเซ็นของสมาชิก สามารถกําหนดการใช้งานในส่วนเดียวกันหรือส่วนอื่น

ไม่จําเป็นต้องมีการดําเนินการสําหรับวิธีการบางส่วนเมื่อลายเซ็นเป็นไปตามกฎต่อไปนี้:

  • การรายงานภาษีไม่มีตัวแก้ไขการเข้าถึงใด ๆ วิธีการ มีการเข้าถึงแบบส่วนตัวตามค่าเริ่มต้น

  • ชนิดผลลัพธ์คือ void

  • ไม่มีพารามิเตอร์ใดที่มีตัวแก้ไข out

  • การประกาศเมธอด ไม่สามารถมีตัวแก้ไขใด ๆ ต่อไปนี้:

    • เสมือน
    • แทนที่
    • ปิด
    • ใหม่
    • extern (ภายนอก)

เมธอด และการเรียกทั้งหมดไปยังเมธอด จะถูกลบออกในเวลาที่คอมไพล์เมื่อไม่มีการนําไปใช้งาน

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

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


// in file1.cs
public partial class PropertyBag
{
    // Defining declaration
    public partial int MyProperty { get; set; }
}

// In file2.cs
public partial class PropertyBag
{
    // Defining declaration
    public partial int MyProperty { get => field; set; }
}

คุณสามารถใช้ field ในตัวเข้าถึง get หรือ set หรือทั้งสองอย่าง

สําคัญ

คําสําคัญ field คือ คุณลักษณะการแสดงตัวอย่างใน C# 13 คุณต้องใช้ .NET 9 และตั้งค่าองค์ประกอบ <LangVersion> ของคุณเพื่อแสดงตัวอย่างในไฟล์โครงการของคุณเพื่อใช้คําสําคัญตามบริบท field

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

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

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

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

    
    // Definition in file1.cs
    partial void OnNameChanged();
    
    // Implementation in file2.cs
    partial void OnNameChanged()
    {
      // method body
    }
    
    
  • การประกาศสมาชิกบางส่วนต้องเริ่มต้นด้วยคําสําคัญเชิงบริบทบางส่วน

  • ลายเซ็นของสมาชิกบางส่วนในทั้งสองส่วนของชนิดบางส่วนต้องตรงกัน

  • สมาชิกบางส่วนสามารถมีตัวแก้ไขแบบคงที่และไม่ปลอดภัยได้

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

  • คุณสามารถสร้างผู้รับมอบสิทธิ์ไปยังเมธอดบางส่วนที่กําหนดและนํามาใช้ แต่ไม่ใช่วิธีการบางส่วนที่ไม่มีการใช้งาน