Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C#

ความแตกต่างระหว่าง Dynamic Type และ Object Type ใน C#

Dynamic vs Object Type ใน C#

ทั้งคู่สามารถเก็บค่าได้ทุกชนิด แต่ **เวลาที่ตรวจสอบชนิด (Type Checking)** และ **ความสามารถ** ต่างกัน

object Type (System.Object)

  • Base class ของทุก Type ใน .NET (Common Type System)
  • **Static Typing** - ตรวจสอบชนิดข้อมูล **Compile-time**
  • ต้อง **Cast** (Boxing/Unboxing) เพื่อใช้งานสมาชิกเฉพาะชนิด
  • Performance: Boxing/Unboxing overhead สำหรับ Value Types

object obj = 100;           // Boxing (int → object)
object str = "Hello";       // Reference assignment
object list = new List(); 

// ต้อง Cast เพื่อใช้งาน
int num = (int)obj;         // Unboxing - throw InvalidCastException ถ้าผิด
string s = (string)str;

// ใช้ with pattern matching (C# 7+)
if (obj is int i) Console.WriteLine(i);
switch (obj)
{
    case int i: Console.WriteLine($"Int: {i}"); break;
    case string st: Console.WriteLine($"String: {st}"); break;
}

dynamic Type (C# 4.0+)

  • **Dynamic Typing** - ตรวจสอบชนิดข้อมูล **Runtime** (DLR - Dynamic Language Runtime)
  • **ไม่ต้อง Cast** - เรียก Member ใดๆ ได้ (Method, Property, Operator)
  • Error จะเกิด **Runtime** (RuntimeBinderException) ไม่ใช่ Compile-time
  • รองรับ COM Interop, Dynamic Languages (IronPython), JSON, XML

dynamic dyn = 100;
dyn = "Hello";
dyn = new List { 1, 2, 3 };

// เรียก member ได้เลย ไม่ต้อง cast
Console.WriteLine(dyn.Count);      // 3 (List.Count)
Console.WriteLine(dyn.Length);     // RuntimeBinderException! (List ไม่มี Length)
dyn.Add(4);                        // เรียก Method ได้
dyn.NonExistentMethod();           // RuntimeBinderException

// Dynamic กับ Anonymous Type
dynamic anon = new { Name = "John", Age = 30 };
Console.WriteLine(anon.Name); // "John" - ไม่ต้อง reflection!

ตารางเปรียบเทียบ

คุณสมบัติobjectdynamic
Type CheckingCompile-time (Static)Runtime (Dynamic)
IntelliSense/IDE Supportเต็มรูปแบบไม่มี (Unknown at compile time)
Performanceเร็ว (Direct/Boxing)ช้ากว่า (DLR Call Site Cache)
Boxing/UnboxingValue types ต้อง BoxingInternal boxing แต่จัดการให้
Member Accessต้อง Cast/Reflectionเรียกได้เลย (Runtime resolve)
Error DetectionCompile-timeRuntime (RuntimeBinderException)
InheritanceBase class ของทุกอย่างไม่ใช่ Type จริง (Compiler trick)

เมื่อไหร่ควรใช้ dynamic?

  • Interop กับ Dynamic Languages (Python, JavaScript via JS engines)
  • COM Objects (Office Automation, Windows Scripting)
  • JSON/XML Parsing แบบไม่มี Schema คงที่
  • Reflection-heavy code ทำให้สั้นลง
  • Duck Typing scenarios

เมื่อไหร่ควรใช้ object?

  • General purpose "any type" container
  • ต้องการ Compile-time safety
  • Performance critical
  • Pattern matching (C# 7+) ทำงานได้ดีกับ object

ตัวอย่าง: JSON Parsing


// ใช้ dynamic กับ Newtonsoft.Json / System.Text.Json
string json = @"{ ""name"": ""John"", ""age"": 30, ""active"": true }";

// System.Text.Json (C# 10+)
dynamic data = System.Text.Json.JsonSerializer.Deserialize(json);
Console.WriteLine(data.name);  // John - ไม่ต้อง define class!
Console.WriteLine(data.age);   // 30

// แต่ถ้าผิด property name
// Console.WriteLine(data.nmae); // RuntimeBinderException ไม่ใช่ Compile error

ExpandoObject - Dynamic Object แบบเพิ่ม Member ได้


using System.Dynamic;

dynamic expando = new ExpandoObject();
expando.Name = "Dynamic";
expando.Age = 25;
expando.SayHello = new Action(() => Console.WriteLine($"Hi {expando.Name}"));

expando.SayHello(); // Hi Dynamic
// เพิ่ม property ได้ตลอด
expando.Country = "Thailand";

สรุป

object = Safe, Fast, Compile-time checking, ต้อง Cast
dynamic = Flexible, Late-binding, Runtime errors, ใช้ตอนจำเป็นจริงๆ