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

ค่าคงที่และฟิลด์ readonly

แยกความแตกต่างระหว่าง const กับ static readonly

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

สองวิธีในการทำให้ค่าคงที่

C# มี const และ readonly สำหรับค่าที่ไม่ควรเปลี่ยนแปลง ทั้งสองดูคล้ายกันแต่มีการทำงานแตกต่างกันมาก บทเรียนนี้จะเปรียบเทียบทั้งสองแบบ

using System;

class Config
{
    public const double Pi = 3.14159;
    public static readonly DateTime StartedAt = DateTime.Now;
}

class Program
{
    static void Main()
    {
        Console.WriteLine("Pi = " + Config.Pi);
    }
}

const: ค่าคงที่ขณะคอมไพล์

const ต้องกำหนดค่าตามตัวอักษรตั้งแต่ตอนประกาศ และค่าจะถูกฝังไว้ตั้งแต่เวลาคอมไพล์ โดยมีสถานะเป็นสแตติกโดยปริยาย

using System;

class Circle
{
    public const double Pi = 3.14159;

    public static double Area(double r) => Pi * r * r;
}

class Program
{
    static void Main()
    {
        Console.WriteLine(Circle.Area(2).ToString("0.00"));
    }
}

const ต้องเป็นค่าตามตัวอักษร

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

using System;

class Limits
{
    public const int MaxRetries = 3;
    public const int Timeout = MaxRetries * 1000;   // const expression OK
}

class Program
{
    static void Main()
    {
        Console.WriteLine(Limits.MaxRetries + ", " + Limits.Timeout);
    }
}

readonly: ค่าคงที่ขณะทำงาน

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

using System;

class Session
{
    public readonly string Id;

    public Session(string id)
    {
        Id = id;   // allowed: inside constructor
    }
}

class Program
{
    static void Main()
    {
        var s = new Session("abc-123");
        Console.WriteLine("Session: " + s.Id);
    }
}

readonly ใช้ค่าขณะทำงานได้

ต่างจาก const ฟิลด์ readonly สามารถเก็บค่าที่จะทราบได้เมื่อโปรแกรมทำงานเท่านั้น เช่น รหัสที่สร้างขึ้นหรือเวลาปัจจุบัน

using System;

class Order
{
    public readonly Guid OrderId;

    public Order()
    {
        OrderId = Guid.NewGuid();
    }
}

class Program
{
    static void Main()
    {
        var o = new Order();
        Console.WriteLine("Has id: " + (o.OrderId != Guid.Empty));
    }
}

static readonly

ใช้ static readonly ร่วมกันสำหรับค่าระดับคลาสที่คำนวณเพียงครั้งเดียวในเวลาทำงาน วิธีนี้เป็นตัวแทนที่ใช้กันทั่วไปแทน const เมื่อค่าไม่ใช่ค่าตามตัวอักษร

using System;

class AppInfo
{
    public static readonly string[] Roles = { "admin", "user", "guest" };
}

class Program
{
    static void Main()
    {
        Console.WriteLine("Roles: " + Roles());
    }

    static int Roles() => AppInfo.Roles.Length;
}

เหตุใดค่าคงที่จึงอาจมีความเสี่ยงเมื่อข้ามชุดแอสเซมบลี

เนื่องจากค่าของ const ถูกฝังลงในโค้ดของผู้เรียกใช้ขณะคอมไพล์ การเปลี่ยนค่าคงที่สาธารณะในไลบรารีจึงต้องคอมไพล์โค้ดของผู้เรียกใช้ทั้งหมดใหม่ ส่วน static readonly ช่วยหลีกเลี่ยงปัญหานี้ได้

using System;

class Lib
{
    public const int Version = 2;              // inlined into callers
    public static readonly int Build = 100;     // read at runtime
}

class Program
{
    static void Main()
    {
        Console.WriteLine(Lib.Version + "." + Lib.Build);
    }
}

ไม่สามารถกำหนดค่าใหม่ให้ทั้งสองแบบได้

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

using System;

class Demo
{
    public const int A = 10;
    public readonly int B;

    public Demo() { B = 20; }
    // A = 11;  // would not compile
    // B = 21;  // would not compile outside constructor
}

class Program
{
    static void Main()
    {
        var d = new Demo();
        Console.WriteLine(Demo.A + ", " + d.B);
    }
}

การเลือกใช้งานระหว่างสองแบบ

ใช้ const กับค่าลิเทอรัลที่แท้จริงและไม่เคยเปลี่ยนแปลง เช่น Pi และ MaxInt ใช้ readonly เมื่อค่าถูกคำนวณขณะทำงานหรืออาจแตกต่างกันในแต่ละอินสแตนซ์

using System;

class Physics
{
    public const double Gravity = 9.81;          // universal literal
    public readonly double Mass;                  // per object

    public Physics(double mass) { Mass = mass; }
    public double Weight() => Mass * Gravity;
}

class Program
{
    static void Main()
    {
        var p = new Physics(10);
        Console.WriteLine("Weight: " + p.Weight());
    }
}

ข้อควรระวังเกี่ยวกับการอ้างอิงแบบอ่านได้อย่างเดียว

readonly จะล็อกฟิลด์ ไม่ใช่อ็อบเจ็กต์ที่ฟิลด์นั้นชี้ไป การอ้างอิงรายการแบบอ่านได้อย่างเดียวไม่สามารถกำหนดใหม่ได้ แต่เนื้อหาภายในยังเปลี่ยนแปลงได้

using System;
using System.Collections.Generic;

class Cart
{
    public readonly List<string> Items = new List<string>();
}

class Program
{
    static void Main()
    {
        var c = new Cart();
        c.Items.Add("Pen");   // allowed: mutating the object
        c.Items.Add("Book");
        Console.WriteLine("Items: " + c.Items.Count);
    }
}

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

คลาสทั่วไปใช้ const กับค่าลิเทอรัลคงที่ และใช้ readonly กับค่าที่กำหนดให้คงที่สำหรับแต่ละอินสแตนซ์ขณะสร้าง

using System;

class Account
{
    public const decimal MinBalance = 0m;
    public readonly string Owner;

    public Account(string owner)
    {
        Owner = owner;
    }
}

class Program
{
    static void Main()
    {
        var a = new Account("Rin");
        Console.WriteLine(a.Owner + " min=" + Account.MinBalance);
    }
}

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

ทดสอบความเข้าใจของคุณเกี่ยวกับ const และ readonly

ทบทวน

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

using System;

class Demo
{
    public const int Max = 100;
    public readonly int Created;
    public Demo(int c) { Created = c; }
}

class Program
{
    static void Main()
    {
        var d = new Demo(7);
        Console.WriteLine(Demo.Max + ", " + d.Created);
    }
}

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

บทเรียน “ค่าคงที่และฟิลด์ readonly” ฟรีหรือไม่

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

คุณจะเรียนรู้อะไรในบทเรียน “ค่าคงที่และฟิลด์ readonly”

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

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

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

บทเรียน “ค่าคงที่และฟิลด์ readonly” ใช้เวลานานแค่ไหน

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

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

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

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

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