C# มี 2 ประเภทตัวแปรระดับ Class: Static Variables (Static Fields) และ Instance Variables (Instance Fields)
Static Variables (Class Variables)
เป็นของ Type เอง ไม่ใช่ Instance แชร์ค่าให้ทุก Instance
using System;
public class StaticVar
{
public static int Count = 0; // Static Field
public StaticVar()
{
Count++; // เพิ่มทุกครั้งที่สร้าง Instance
}
public static void Reset() => Count = 0;
}
public class Program
{
public static void Main()
{
var s1 = new StaticVar();
var s2 = new StaticVar();
var s3 = new StaticVar();
Console.WriteLine(StaticVar.Count); // 3 - แชร์ค่าเดียวกัน
StaticVar.Reset();
Console.WriteLine(StaticVar.Count); // 0
}
}
Instance Variables (Class Variables / Fields)
เป็นของแต่ละ Instance แยกต่างหาก
public class Box
{
// Private Fields (Encapsulation)
private double _length;
private double _breadth;
private double _height;
// Public Properties (Accessors)
public double Length
{
get => _length;
set => _length = value > 0 ? value : throw new ArgumentException("Length must be positive");
}
public double Breadth { get => _breadth; set => _breadth = value; }
public double Height { get => _height; set => _height = value; }
// Method
public double GetVolume() => _length * _breadth * _height;
}
public class Program
{
public static void Main()
{
Box box1 = new Box { Length = 6, Breadth = 7, Height = 5 };
Box box2 = new Box { Length = 12, Breadth = 13, Height = 10 };
Console.WriteLine($"Box1 Volume: {box1.GetVolume()}"); // 210
Console.WriteLine($"Box2 Volume: {box2.GetVolume()}"); // 1560
}
}
ผลลัพธ์
Box1 Volume: 210
Box2 Volume: 1560
Static vs Instance - ตารางเปรียบเทียบ
| ด้าน | Static Field | Instance Field |
|---|---|---|
| Memory | 1 ต่อ Type (AppDomain) | 1 ต่อ Instance |
| Lifetime | Process Duration | Instance Lifetime |
| Access | ClassName.Field | instance.Field |
| Thread Safety | ต้อง Lock เอง | แยก Instance แยกกัน |
| Inheritance | ซ่อน (Hiding) ไม่ Override | Override ได้ (ถ้า Virtual) |
| Serialization | มักไม่ Serialize | Serialize ปกติ |
Static Constructor
public class Config
{
public static string ConnectionString { get; private set; }
public static int MaxConnections { get; private set; }
// Static Constructor - รันครั้งเดียวก่อน First Access
static Config()
{
Console.WriteLine("Static Constructor Running...");
ConnectionString = LoadFromConfig();
MaxConnections = 100;
}
private static string LoadFromConfig() => "Server=...";
}
Constants vs Static Readonly
public class Constants
{
// Compile-time Constant - ต้องเป็น Literal, Implicit Static
public const double PI = 3.14159265359;
// Runtime Constant - สามารถคำนวณได้, ใช้กับ Object ได้
public static readonly DateTime AppStartTime = DateTime.Now;
// Static Readonly with Complex Init
public static readonly string[] SupportedFormats =
Directory.GetFiles("formats", "*.fmt").Select(Path.GetFileName).ToArray();
}
Best Practices
- Static Fields: ใช้สำหรับ Shared State, Constants, Caches, Counters
- Instance Fields: ใช้สำหรับ Object State (Data per Object)
- หลีกเลี่ยง Public Fields → ใช้ Properties
- Static Mutable State → Thread Safety (Lock, Interlocked, Concurrent Collections)
- Prefer `static readonly` over `const` สำหรับ Complex Types