kritsana.devpassing
runartifactsdocsworkhistorydispatch

© 2026 Kritsana Prasit — built from source on a self-hosted runner

resume.pdfrssdispatch

back to artifacts
category: software engineeringdate: 12 Nov 2026read: 3 min readsource: posts/whats-new-in-dotnet-11-summary.mdxtrending

สรุป .NET 11 มีอะไรใหม่? ฉบับเพื่อนเล่าให้ฟัง: Runtime Async, FullJoin และของเล่นใหม่ที่ช่วยให้เขียนโค้ดเหนื่อยน้อยลง

สรุปไฮไลต์ .NET 11 จาก PVS-Studio แบบกระชับเข้าใจง่าย ตั้งแต่ Runtime Async ที่ย้ายงานจากคอมไพเลอร์ลง Runtime, คำสั่งรัน Process บรรทัดเดียว ไปจนถึงข้อควรระวังเรื่อง CPU รุ่นเก่า

สรุป .NET 11 มีอะไรใหม่? ฉบับเพื่อนเล่าให้ฟัง: Runtime Async, FullJoin และของเล่นใหม่ที่ช่วยให้เขียนโค้ดเหนื่อยน้อยลง

เพิ่งได้อ่านบทความสรุป What's new in .NET 11? ของทีม PVS-Studio มาแล้วรู้สึกว่ารอบนี้ Microsoft ทำการบ้านมาดีมาก คือไม่ได้เน้นแค่เพิ่มฟีเจอร์หวือหวา แต่เข้าไปแก้จุดที่คนเขียน C# รำคาญใจในชีวิตประจำวันจริงๆ

เลยหยิบมาสรุปแบบสั้นๆ เหมือนเพื่อนเล่าให้ฟังว่าถ้าจะขยับไป .NET 11 (ซึ่งเป็นรุ่น STS ที่ซัพพอร์ตยาว 2 ปีเต็ม) มีอะไรที่เราจะได้ใช้แน่ๆ และมีเรื่องไหนต้องระวังก่อนอัปเกรดบ้าง

ภาพปก .NET 11


1. พระเอกตัวจริง: Runtime Async (ไม่ต้องพึ่ง State Machine แบบเดิมแล้ว)

ปกติเวลาเราเขียน async / await คอมไพเลอร์ C# จะแอบไปสร้างโค้ด State Machine ก้อนใหญ่ๆ ไว้เบื้องหลัง ซึ่งบางทีก็ทำให้เปลืองหน่วยความจำ และเวลาไล่ Stack Trace หรือกด Step Over ตอนดีบักก็มักจะกระโดดเข้าไปในโค้ดภายในของระบบจนตาลาย

ใน .NET 11 เขาย้ายหน้าที่การจัดการ async ลงไปให้ Runtime ดูแลโดยตรงแทน (ตัว Core Libraries ของ .NET 11 เองก็คอมไพล์ด้วยโหมดนี้เรียบร้อยแล้ว)

ผลที่ได้แบบเห็นชัดๆ คือ:

  • เร็วขึ้นและกินแรมน้อยลง: JIT รู้จักโค้ด async โดยตรง ทำให้รีไซเคิลออบเจกต์ได้ และทำ Tiered Compilation กับเมธอดที่ถูกเรียกบ่อยๆ ได้ดีขึ้น
  • ดีบักง่ายขึ้นมาก: เวลาดู StackTrace จะเห็นเฉพาะลำดับการเรียกฟังก์ชันของเราจริงๆ ไม่มีโค้ดขยะของระบบมาคั่น และกดข้าม await ได้เนียนเหมือนโค้ดปกติ

ถ้าอยากเปิดใช้ในโปรเจกต์ตัวเอง แค่เติมบรรทัดนี้ลงในไฟล์ .csproj (ไม่ต้องเปิด EnablePreviewFeatures แล้ว):

xml
<PropertyGroup>
  <Features>runtime-async=on</Features>
</PropertyGroup>

2. สั่งรัน Process แล้วเก็บ Output ได้ในบรรทัดเดียวสักที!

ใครเคยใช้คลาส Process เพื่อสั่งรันคำสั่ง CLI (เช่น git หรือสคริปต์ข้างนอก) จะรู้ว่าเมื่อก่อนต้องเขียนโค้ดยาวเหยียด ต้องคอยผูก OutputDataReceived หรือเปิดอ่าน Stream เอง

ใน .NET 11 มี Process.RunAndCaptureTextAsync มาให้แล้ว จบในบรรทัดเดียวแบบนี้เลย:

csharp
ProcessTextOutput result = await Process.RunAndCaptureTextAsync(
    "git",
    ["status", "--porcelain"]
);
 
Console.WriteLine(result.StandardOutput);
Console.WriteLine($"Exit code: {result.ExitStatus.ExitCode}");

นอกจากนี้ยังมี Process.StartAndForget สำหรับสั่งรันทิ้งไว้โดยไม่ต้องรอให้จบอีกด้วย


3. LINQ มี FullJoin แล้ว (และ Join ไม่บังคับใส่ selector ยาวๆ)

หลังจากที่เวอร์ชันก่อนเพิ่ม LeftJoin กับ RightJoin มาให้ รอบนี้ LINQ เติม FullJoin เข้ามาจนครบตระกูลแล้ว มันจะดึงข้อมูลทั้งสองฝั่งมาจับคู่กัน ถ้าฝั่งไหนไม่มีคู่ก็จะเก็บไว้โดยใส่ค่าว่างให้อีกฝั่ง

แถมทั้ง Join, GroupJoin, LeftJoin, RightJoin และ FullJoin ตอนนี้เรียกใช้โดยไม่ต้องเขียนฟังก์ชัน resultSelector ปิดท้ายได้แล้ว เพราะมันคืนค่ากลับมาเป็น Tuple ให้แกะใช้ได้เลย:

csharp
var joined = products.FullJoin(categories, p => p.Category, c => c.Name);
 
foreach (var (product, category) in joined)
{
    Console.WriteLine($"{product.Name ?? "(none)"} : {category.Description ?? "(none)"}");
}

4. ของใหม่ใน Libraries ที่ช่วยชีวิตตอนเขียนงานจริง

นอกจากสองตัวบน ยังมี API เล็กๆ น้อยๆ ที่เพิ่มเข้ามาแล้วมีประโยชน์มาก:

  • Async Validation (IAsyncValidatableObject / AsyncValidationAttribute): เมื่อก่อนเวลาทำ Data Annotations Validation เราเช็กแบบ Async ไม่ได้ (เช่น ต้องยิงไปถาม Database ว่าอีเมลซ้ำไหม) ตอนนี้มี Validator.ValidateObjectAsync และรองรับการเช็ก Options ตอนเปิดแอปผ่าน IAsyncStartupValidator แล้ว
  • TryParsePartial อ่านตัวเลขเท่าที่อ่านไหว: ปกติถ้าสตริงเป็น "123;789" แล้วใช้ double.TryParse มันจะพังและคืนค่า 0 ทันที แต่ถ้าใช้ double.TryParsePartial มันจะอ่านเลข 123 ออกมาให้ พร้อมบอกว่าอ่านไปกี่ตัวอักษร (consumed = 3) เหมาะกับงานแกะไฟล์ข้อมูลดิบมาก
  • รองรับบีบอัดไฟล์แบบ Zstandard (ZstandardStream) ในตัว: ไม่ต้องหาไลบรารีแยกแล้ว แถมตัวอ่านไฟล์ ZIP ตอนนี้เช็กค่า CRC32 ให้อัตโนมัติ และเปิดไฟล์ ZIP ที่ติดรหัสผ่านได้ด้วย
  • Stream แบบไม่ต้องก๊อปปี้ข้อมูลซ้ำ: เพิ่ม ReadOnlyMemoryStream, WritableMemoryStream, ReadOnlySequenceStream และ StringStream ช่วยให้ส่ง Buffer หรือ String เข้า API ที่รับ Stream ได้เลยโดยไม่สร้างขยะให้ GC ตามเก็บ
  • System.Text.Json ฉลาดขึ้น: รองรับ union type ของ C# 15, เขียนไฟล์แบบ JSON Lines (JSONL) ได้ในตัว, มี JsonNamingPolicy.PascalCase และมี InferClosedTypePolymorphism = true ที่ช่วยเดาคลาสลูกของ closed record ให้อัตโนมัติโดยไม่ต้องนั่งแปะ [JsonDerivedType] ทีละตัว:
csharp
[JsonPolymorphic(InferClosedTypePolymorphism = true)]
closed record Shape;
record Circle(double Radius) : Shape;
record Square(double Length) : Shape;
  • ชนิดตัวเลขทศนิยมมาตรฐาน IEEE 754-2019: เพิ่ม Decimal32, Decimal64, Decimal128 ใน System.Numerics ที่เก็บค่าฐาน 10 เป๊ะเหมือน decimal (เช่น 0.1 ไม่เพี้ยน) แต่รองรับ NaN และ Infinity สำหรับคุยกับฐานข้อมูลหรือภาษาอื่น

5. SDK & CLI เร็วขึ้นจนรู้สึกได้

  • dotnet CLI คอมไพล์เป็น NativeAOT แล้ว: เวลาพิมพ์คำสั่งพื้นฐานอย่าง dotnet --version, dotnet --info หรือเรียกเครื่องมือเสริมอย่าง dotnet ef มันจะทำงานแบบ Native ทันที ไม่ต้องรอโหลดรันไทม์ชุดใหญ่ก่อน
  • รันไฟล์ .cs เดี่ยวๆ แยกไฟล์ได้แล้ว: ต่อยอดจาก .NET 10 ที่รันไฟล์ .cs เดี่ยวๆ ได้ ตอนนี้มีคำสั่ง #:include ให้ดึงไฟล์ .cs อื่นหรือไฟล์ .dll มาร่วมใช้ได้โดยยังไม่ต้องสร้างไฟล์โปรเจกต์
  • ส่ง Environment Variable ตอนรันได้ง่ายๆ: ใช้แฟล็ก dotnet run -e KEY=VALUE ได้เลย และ dotnet test มีโหมดทดลองที่เลือกรันเฉพาะเทสต์ที่กระทบจากโค้ดที่เราเพิ่งแก้

ข้อควรระวังก่อนอัปเกรด: เช็กสเปก CPU ของเซิร์ฟเวอร์ด้วย!

เรื่องเดียวที่ต้องเช็กก่อนอัปเกรดคือ .NET 11 ขยับสเปกขั้นต่ำของซีพียูฝั่ง x86/x64 ขึ้นเป็น x86-64-v2 (จากเดิม v1):

  • ถ้าเอาไปรันบนเครื่องหรือ VM รุ่นเก่ามากๆ ที่ไม่รองรับชุดคำสั่ง x86-64-v2 แอปจะ เปิดไม่ติดเลย
  • ส่วนอิมเมจแบบ ReadyToRun บน Windows และ Linux ขยับไปเล็งที่ x86-64-v3 (AVX2, BMI2, FMA) ถ้าซีพียูไม่ถึง v3 แอปยังรันได้ปกติ แต่ตอนเปิดโปรแกรมจะช้าลงนิดหน่อยเพราะต้องให้ JIT คอมไพล์ใหม่แทน

สรุปสั้นๆ คุ้มไหมที่จะอัปเกรด?

ถ้าเครื่องเซิร์ฟเวอร์ไม่ได้เก่าเกิน 10 ปี การขยับไป .NET 11 กับ C# 15 รอบนี้คุ้มมาก ได้ทั้งความเร็วจาก JIT และ Runtime Async ฟรีๆ แถมได้ของใช้อย่าง Process.RunAndCaptureTextAsync, FullJoin และ AsyncValidation ที่ช่วยลดโค้ดรกๆ ในโปรเจกต์ลงไปได้เยอะเลย

contents

  • 1. พระเอกตัวจริง: Runtime Async (ไม่ต้องพึ่ง State Machine แบบเดิมแล้ว)
  • 2. สั่งรัน Process แล้วเก็บ Output ได้ในบรรทัดเดียวสักที!
  • 3. LINQ มี `FullJoin` แล้ว (และ `Join` ไม่บังคับใส่ selector ยาวๆ)
  • 4. ของใหม่ใน Libraries ที่ช่วยชีวิตตอนเขียนงานจริง
  • 5. SDK & CLI เร็วขึ้นจนรู้สึกได้
  • ข้อควรระวังก่อนอัปเกรด: เช็กสเปก CPU ของเซิร์ฟเวอร์ด้วย!
  • สรุปสั้นๆ คุ้มไหมที่จะอัปเกรด?

related documents

software engineering · 1
  • ทำไมการเขียนซอฟต์แวร์ให้ "ถูกต้อง" ถึงยากอย่างที่คิด: Halting Problem กับข้อจำกัดของการพิสูจน์

    13 Nov 2026 · 4 min read

comments