0Pricing
C# Academy · บทเรียน

การออกแบบแบบสแตติกกับแบบอินสแตนซ์

ตัดสินใจว่าเมื่อใดจึงควรใช้สถานะแบบสแตติก

การออกแบบแบบสแตติกกับแบบอินสแตนซ์ เป็นบทเรียน C# Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C# Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C# Academy มีบทเรียนทั้งหมด 4 บทเรียน

การตัดสินใจด้านการออกแบบ

การเลือกระหว่าง แบบสแตติก กับ แบบอินสแตนซ์ เป็นการตัดสินใจด้านการออกแบบ คำถามสำคัญคือ พฤติกรรมขึ้นอยู่กับสถานะของแต่ละอ็อบเจ็กต์ หรือขึ้นอยู่กับข้อมูลนำเข้าเท่านั้น

using System;

class Program
{
    // Depends only on inputs -> good static method
    static int Max(int a, int b) => a > b ? a : b;

    static void Main()
    {
        Console.WriteLine(Max(3, 8));
    }
}

ใช้สมาชิกแบบสแตติกสำหรับตรรกะไร้สถานะ

หากวิธีการไม่จำเป็นต้องใช้ฟิลด์ของอินสแตนซ์และเพียงแปลงข้อมูลนำเข้า ให้กำหนดวิธีการนั้นเป็น static ตัวช่วยทางคณิตศาสตร์และตัวจัดรูปแบบเป็นตัวอย่างที่เหมาะสม

using System;

static class Convert2
{
    public static double MilesToKm(double miles) => miles * 1.60934;
}

class Program
{
    static void Main()
    {
        Console.WriteLine(Convert2.MilesToKm(10).ToString("0.0") + " km");
    }
}

ใช้สมาชิกแบบอินสแตนซ์สำหรับสถานะ

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

using System;

class Counter
{
    private int _count;
    public void Increment() => _count++;
    public int Value => _count;
}

class Program
{
    static void Main()
    {
        var a = new Counter();
        var b = new Counter();
        a.Increment();
        a.Increment();
        b.Increment();
        Console.WriteLine("a=" + a.Value + ", b=" + b.Value);
    }
}

สถานะร่วมก็คือสถานะส่วนกลาง

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

using System;

class BadCart
{
    public static int Items;   // shared by EVERYONE -> usually wrong for a cart
}

class Program
{
    static void Main()
    {
        BadCart.Items++;
        BadCart.Items++;
        Console.WriteLine("All carts share: " + BadCart.Items);
    }
}

ความสามารถในการทดสอบ

วิธีการแบบสแตติกที่บริสุทธิ์ทดสอบได้ง่าย: ข้อมูลนำเข้าเหมือนเดิม ผลลัพธ์ก็เหมือนเดิม แต่สถานะแบบสแตติกที่เปลี่ยนแปลงได้จะรั่วไหลระหว่างการทดสอบและทำให้การทดสอบเปราะบาง

using System;

static class Calc
{
    public static int Add(int a, int b) => a + b;   // trivially testable
}

class Program
{
    static void Main()
    {
        Console.WriteLine(Calc.Add(2, 2) == 4 ? "pass" : "fail");
    }
}

ใช้สมาชิกแบบสแตติกเป็นตัวช่วยสร้าง

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

using System;

class Color
{
    public int R, G, B;
    private Color(int r, int g, int b) { R = r; G = g; B = b; }

    public static Color Red() => new Color(255, 0, 0);
    public static Color White() => new Color(255, 255, 255);
}

class Program
{
    static void Main()
    {
        var c = Color.Red();
        Console.WriteLine(c.R + "," + c.G + "," + c.B);
    }
}

อย่าใช้สมาชิกแบบสแตติกเพียงเพื่อหลีกเลี่ยงการสร้างอ็อบเจ็กต์

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

using System;

class Player
{
    public string Name;
    public int Health = 100;
    public void TakeDamage(int d) => Health -= d;
}

class Program
{
    static void Main()
    {
        var p1 = new Player { Name = "A" };
        var p2 = new Player { Name = "B" };
        p1.TakeDamage(30);
        Console.WriteLine(p1.Name + ": " + p1.Health + ", " + p2.Name + ": " + p2.Health);
    }
}

ผสมผสานทั้งสองแบบอย่างเหมาะสม

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

using System;

class Invoice
{
    private static int _seq = 1000;
    public readonly int Number;
    public decimal Amount;

    public Invoice(decimal amount)
    {
        Number = _seq++;
        Amount = amount;
    }
}

class Program
{
    static void Main()
    {
        var i1 = new Invoice(50m);
        var i2 = new Invoice(75m);
        Console.WriteLine(i1.Number + " / " + i2.Number);
    }
}

ข้อควรคำนึงถึงการทำงานพร้อมกัน

หลายเธรดอาจเข้าถึงสถานะแบบสแตติกร่วมกันในเวลาเดียวกัน ซึ่งเสี่ยงต่อสภาวะแข่งขัน สถานะแบบอินสแตนซ์ที่จำกัดอยู่ในเธรดเดียวจึงปลอดภัยกว่าโดยปริยาย

using System;

class SafeCalc
{
    // No shared mutable state -> naturally thread-safe
    public static long Factorial(int n)
    {
        long result = 1;
        for (int i = 2; i <= n; i++) result *= i;
        return result;
    }
}

class Program
{
    static void Main()
    {
        Console.WriteLine(SafeCalc.Factorial(5));
    }
}

หลักจำง่ายอย่างหนึ่ง

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

using System;

class Temperature
{
    public double Celsius;                                  // instance state
    public static double ToF(double c) => c * 9 / 5 + 32;   // stateless helper
}

class Program
{
    static void Main()
    {
        var t = new Temperature { Celsius = 30 };
        Console.WriteLine(Temperature.ToF(t.Celsius));
    }
}

สรุปการใช้งานร่วมกัน

การออกแบบที่ดีจะแยกตัวช่วยไร้สถานะ (แบบสแตติก) ออกจากแบบจำลองที่มีสถานะ (แบบอินสแตนซ์) และจำกัดสถานะร่วมที่เปลี่ยนแปลงได้ให้น้อยที่สุดเท่าที่ตั้งใจไว้

using System;

static class TaxRules
{
    public static decimal Apply(decimal amount, decimal rate) => amount + amount * rate;
}

class Sale
{
    public decimal Subtotal;
    public decimal Total(decimal rate) => TaxRules.Apply(Subtotal, rate);
}

class Program
{
    static void Main()
    {
        var s = new Sale { Subtotal = 100m };
        Console.WriteLine(s.Total(0.2m));
    }
}

ตรวจสอบความเข้าใจอย่างรวดเร็ว

ทดสอบความเข้าใจของคุณเกี่ยวกับการออกแบบแบบสแตติกและแบบอินสแตนซ์

ทบทวน

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

using System;

static class Util { public static int Sq(int n) => n * n; }

class Box { public int Size; public int Area() => Util.Sq(Size); }

class Program
{
    static void Main()
    {
        var box = new Box { Size = 4 };
        Console.WriteLine(box.Area());
    }
}

คำถามที่พบบ่อย

บทเรียน “การออกแบบแบบสแตติกกับแบบอินสแตนซ์” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การออกแบบแบบสแตติกกับแบบอินสแตนซ์” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C# Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C# Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การออกแบบแบบสแตติกกับแบบอินสแตนซ์”

ตัดสินใจว่าเมื่อใดจึงควรใช้สถานะแบบสแตติก คุณปฏิบัติ C# Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C# Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน C# Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “การออกแบบแบบสแตติกกับแบบอินสแตนซ์” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน C# Academy นี้ได้ไหม

ได้ บทเรียน C# Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. เมธอดและฟิลด์แบบสแตติก
  2. คลาสแบบสแตติกสำหรับยูทิลิตี
  3. ค่าคงที่และฟิลด์ readonly
  4. การออกแบบแบบสแตติกกับแบบอินสแตนซ์
← กลับไปที่ C# Academy