Saladpuk.com
🏆 เนื้อหาหลัก
🏆 เนื้อหาหลัก
  • 💖สลัดผัก
  • 📰มีอะไรใหม่บ้าง
    • 2020
      • 2020-11
      • 2020-10
      • 2020-09
      • 2020-08
      • 2020-03
      • 2020-02
      • 2020-01
    • 2019
      • 2019-12
      • 2019-11
      • 2019-10
      • 2019-09
      • 2019-08
  • 🤔อ่านเรื่องไรดี ?
  • มือใหม่หัดเขียนโค้ด
    • 👶เขียนโค้ดด้วยภาษา C#
      • เกิดมาไม่เคยเขียนโค้ดมาก่อนเบย
      • 👶พื้นฐาน
        • 1.โปรแกรมที่ต้องลง
        • 2.โครงสร้างของโค้ด
        • 3.ชนิดของข้อมูล
        • 4.การสร้างตัวแปร
        • 5.คำสั่งพื้นฐาน
        • 6.การแปลงข้อมูล
        • 7.การเปรียบเทียบค่า
        • 8.การตัดสินใจด้วย IF statements
        • 9.การตัดสินใจด้วย Switch statements
        • 10.การทำงานซ้ำๆด้วย While
        • 11.การทำงานซ้ำๆด้วย Do While
        • 12.การทำงานซ้ำๆด้วย For
        • 13.การแก้โจทย์จากรูป
        • 14.มารู้จักกับ Array กัน
      • 🧑ระดับกลาง
        • 15.Value type vs Reference type
        • 16.ลดงานซ้ำๆด้วย Method
        • 17.มารู้จักกับ Class & Field กัน
        • 18.มารู้จักกับ Constructor กันบ้าง
        • 19.มาเขียน Method ใน Class กัน
        • 20.มารู้จักกับ Property กัน
        • 21.ลองใช้คลาสแบบจริงจังบ้าง
        • 22.การสืบทอด Inheritance
        • 23.Polymorphism
        • 24.Abstract Class
        • 25.Interface
        • 26.Namespace
        • 27.Enum
        • 28.Exception handler
        • 29.ลงลึกกับ string
        • 30.StringBuilder เพื่อนคู่ string
      • 👨⏳ระดับสูง
        • Generic
        • Delegates
        • Action & Func
        • Lambda expression
        • LINQ
        • พระคัมภีร์การใช้คำสั่ง LINQ
      • 💡Tips
        • 💡C# version 8.0
        • 💡Boxing & Unboxing
    • 👶Algorithm
      • 👾Algorithm Big-O
      • 👽Algorithm P & NP
    • 👦OOP
      • 💖Abstraction
      • 💖Encapsulation
      • 🏆Abstraction & Encapsulation
      • 💖Inheritance
      • 💖Polymorphism
      • 🏆Inheritance & Polymorphism
      • 📝ลองเขียน OOP ดูดิ๊
      • 👑OOP + Power of Design
      • 🥰เทคนิคในการออกแบบ
    • 👶บทสรุปฐานข้อมูล
      • เก็บรูปในฐานข้อมูล
      • Database indexing
      • การลบข้อมูล
    • 👦Communication Patterns
    • 👦Design Patterns
      • 🤰Creational Patterns
        • 🏭Factory Method
        • 🏭Abstract Factory
        • ☝️ Singleton Pattern
        • 🏗️ Builder Pattern
        • 🎎Prototype Pattern
      • 🧱Structural Patterns
        • 🔌Adapter Pattern
        • 📪Proxy Pattern
  • Puzzle
    • 🧠Challenges
      • 🐴Google ม้า 25 ตัว
      • 🌉Amazon เสา 2 ต้น
      • 🥇ทองเก๊
      • 💊ยาต้านโควิด
      • 🎩CP หมวก 5 ใบ
      • 🧓Einstein's Riddle 01
  • พื้นฐานที่ควรต้องรู้
    • 🐳Docker
      • 📦Docker Containers
      • 🃏Docker Exercise 01
      • 🛠️ Docker Tools
      • 🗃️ Docker Registry
      • 🖼️ Container Image
      • 📢Docker Push
      • 🔄WSL
    • 👶Clean Code
      • 🧓Uncle Bob - Clean Code
      • 🧓Uncle Bob - Comments
      • 🧓Uncle Bob - Naming
      • 🧓Uncle Bob - Mindset
      • 🧓Uncle Bob - TDD
    • 👶Code Smells
    • 👶สิ่งที่คนเขียนโค้ดมักเข้าใจผิด
    • 👶AI พื้นฐาน
    • 👶Git พื้นฐาน
      • Git branching strategy
    • 👶Cloud พื้นฐาน
    • 👶UML พื้นฐาน
      • Activity Diagram
      • Class Diagram
      • Sequence Diagram
      • Use case Diagram
      • บทสรุปการใช้ UML
    • 👶Data Scientist
      • การเลือก Algorithms ให้ AI (1/5)
      • การเตรียมข้อมูลให้ AI (2/5)
      • หลักการตั้งคำถามให้ AI (3/5)
      • แฉความลับของ AI Model (4/5)
      • หัดเขียน AI จาก AI ของคนอื่น (5/5)
    • 👶DevOps พื้นฐาน
    • 👶Docker ขั้นพื้นฐาน
      • Image and Container
      • แชร์ Docker Image ที่สร้างไว้
    • 👶Microservices พื้นฐาน
      • Microservices ที่ดีมีลักษณะยังไง
      • Microservices Tips
      • จาก Monolith สู่ Microservices
    • 👶ความรู้พื้นฐานในการทำเว็บ
    • 👦Bottlenecks of Software
      • หัวใจที่สำคัญที่สุดของฐานข้อมูล
    • 👦Agile Methodology
      • Agile in a Nutshell
      • Software Development Life Cycle
      • Code Review
    • 👦Security พื้นฐาน
      • การเก็บรหัสผ่านที่ถูกต้อง
      • Security in actions
        • Hash function
      • Security Principles
      • 😎The Matrix 1
      • 😎The Matrix 2
      • HTTPS in a nutshell
    • 👦SOLID Design Principles
      • มารู้จักกับ SOLID กันดีกว่า
      • Single-Responsibility Principle
      • Open/Closed Principle
      • Liskov Substitution Principle
      • Interface Segregation Principle
      • Dependency-Inversion Principle
  • Cloud Computing
    • 👶Microsoft Azure 101
      • สมัคร Microsoft Azure
      • รู้จักกับ Resource Groups
      • สร้างเว็บตัวแรกกัน
      • สร้าง Virtual Machine กัน
      • ประเภทของคลาว์เซอร์วิส
      • มาสร้าง Logic App กัน
      • มาสร้าง Function App กัน
      • คลาว์คิดเงินยังไง ?
      • Cloud Native
      • Guideline for Cloud scaling
      • Auto Scaling
    • 👶Azure App Services
    • 👶App Service Plan
    • 👶Azure Storage
      • Blob storage
        • ลองสร้างที่เก็บไฟล์กันเลย
        • เข้าใจ Blob storage ให้มากขึ้น
        • ลองเขียนโค้ดอัพโหลดไฟล์กันบ้าง
        • สร้างเว็บจากที่ฝากไฟล์บนคลาว์
    • 👶Azure Bot Service
      • Bot เข้าใจเราได้ยังไงกันนะ
    • 👶Azure Cognitive Services
      • การสร้าง Cognitive Services
      • การ Login ด้วยใบหน้า
      • อ่านลายมือจากรูปเป็นตัวอักษร (OCR)
      • เขียน AI แยกของต่างๆทำยังไง?
      • เขียนแอพ ทายอายุ บอกเพศ ง่ายจิ๊ดเดียว
      • เขียนแอพให้ AI อธิบายรูปเป็นภาษาคน
    • 👶Machine Learning Studio
      • มาสร้าง AI ของแท้ตัวแรกของเรากัน
      • สร้าง AI ตัดสินใจอนุมัติบัตรเครดิต 💳
      • ลองเรียกใช้ AI ของเรากัน
    • 👶Azure Service Fabric
      • สร้าง Service Fabric กัน
    • 👶Blockchain
      • Blockchain ทำงานยังไง ?
      • Consensus Algorithm คืออะไร ?
      • สร้าง Blockchain ใช้เองกัน !
      • หัดเขียน Smart Contract กัน
    • 👶Power BI
    • 👶Azure Web App
      • เซิฟเวอร์บนคลาว์ ราคา? ต่าง?
    • 👶Azure DevOps
      • เล่น Azure DevOps กัน
      • เล่นกับ Repository
      • ลองทำ Continuous Integration (CI)
      • ลองทำ Continuous Delivery (CD)
      • เล่น Kanban Board
    • 🤠Cloud Playground
      • การป้องกันความลับหลุดตอนที่ 1
      • การป้องกันความลับหลุดตอนที่ 2
      • การป้องกันความลับหลุดตอนที่ 3
      • การป้องกันความลับหลุดตอนจบ
  • Software Testing
    • 👦Test-First Design
    • 👦Test-Driven Development
      • 1.มารู้จักกับ TDD กันดีกว่า
      • 2.Test cases เขาเขียนกันยังไงนะ
      • 3.เครื่องมือในการทดสอบ
      • 4.การใช้ Theory และ InlineData
      • 5.โค้ดที่ทดสอบได้
      • 6.Mantra of TDD
      • 7.Functional & None-Functional testing
      • 8.Manual vs Automation testing
      • 9.Automation Frameworks in .NET
      • 10.Mock Framework
      • 11.มาเรียนการใช้ Moq กันเถอะ
      • 12.สรุป
  • Web
    • 👦Web API
      • 1.Web API คืออะไร
      • 2.ติดตั้ง .NET Core SDK
      • 3.สร้าง Web API ตัวแรกกัน
      • 4.Verbs
      • 5.Swagger เพื่อคู่ API
      • 6.การใช้ Model
      • 7.เรียก Web API ผ่าน Postman
      • 8.มาจัดกลุ่ม API กัน (1/2)
      • 9.มาจัดกลุ่ม API กัน (2/2)
  • Software Design
    • 🤴Design Patterns
      • 🦈Creational patterns
        • Abstract Factory
        • Builder
        • Factory Method
        • Prototype
        • Singleton
      • 🦈Structural patterns
        • Adapter
        • Bridge
        • Decorator
        • Facade
        • Proxy
      • 🦈Behavioral patterns
        • Chain of Responsibility
        • Command
        • Iterator
        • Mediator
        • Memento
        • Observer
        • State
        • Strategy
        • Template Method
        • Visitor
Powered by GitBook
On this page
  • 🔥 Readonly members
  • 🔥 Default interface members
  • 🔥 More patterns in more places
  • 💡 Switch expressions
  • 💡 Property patterns
  • 💡 Tuple patterns
  • 💡 Positional patterns
  • 💡 Recursive patterns
  • 🔥 using declarations
  • 🔥 Static local functions
  • 🔥 Disposable ref structs
  • 🔥 Nullable reference types
  • 🔥 Asynchronous streams
  • 🔥 Indices and ranges
  • 💡 Indices
  • 💡 Ranges
  • 🔥 Null-coalescing assignment
  • 🔥 Unmanaged constructed types
  • 🔥 Enhancement of interpolated verbatim strings
  • 🎥 วีดีโอประกอบความเข้าใจ

Was this helpful?

Export as PDF
  1. มือใหม่หัดเขียนโค้ด
  2. เขียนโค้ดด้วยภาษา C#
  3. Tips

C# version 8.0

�� ภาษา C# เวอร์ชั่น 8.0 มีอะไรใหม่ๆบ้าง

หลายๆคนอาจจะเคยเห็นในอินเตอร์เน็ทเขาเขียนภาษา C# ในรูปแบบที่เราไม่เคยเห็นมาก่อน แล้วพอเราไปทำตามก็เขียนแบบนั้นไม่ได้ นั่นเป็นเพราะภาษา C# ในแต่ละเวอร์ชั่นเขาได้มีการเพิ่มความสามารถใหม่ๆเข้าไปเสมอนั่นเอง แล้วถ้าเราอยากใช้ความสามารถใหม่ๆพวกนั้น เราก็ต้องทำการอัพเดทตัว C# เวอร์ชั่นของเราด้วยถึงจะใช้ได้ ดังนั้นในรอบนี้เราจะมาดูกันว่า C# เวอร์ชั้น 8.0 จะมีความสามารถอะไรใหม่ๆมาให้เราลองเล่นกันบ้าง

🔥 Readonly members

ใน struct ได้ถูกเพิ่มความสามารถให้ใช้ readonly ให้กับ member ของมันได้ เพื่อเป็นการกำหนดให้ member ตัวนั้นๆต้องไม่ไปทำการเปลี่ยนค่าของ member อื่นๆ เช่นโค้ดด้านล่าง จะเป็น struct ที่มีการไปแก้ไขค่าให้กับ member อื่น

 public struct Something
 {
     public int X { get; set; }
     
     public override string ToString()
     {
         X = 77.9;
         return $"The value of X is: {X}";
     }
 }

จากโค้ดด้านบนถ้าเราไม่อยากให้ ToString() แก้ไขเปลี่ยนแปลง member อื่นๆได้ เราก็สามารถใส่ readonly เข้าไปได้ตามโค้ดด้านล่างครับซึ่งมันจะบังคับให้เราแก้ไข member อื่นไม่ได้เลย เพราะมันจะ compile ไม่ผ่านนั่นเอง

public struct Something
 {
     public int X { get; set; }
     
     public readonly override string ToString()
     {
         // X = 77.9; ต้องเอาบรรทัดนี้ออกไม่งั้น compile ไม่ผ่าน
         return $"The value of X is: {X}";
     }
 }

🔥 Default interface members

โดยปรกติ Interface นั้นเราจะไม่สามารถมี member ที่มี implementation ภายในได้ แต่ด้วยความสามารถใหม่นี้จะทำให้เราสร้าง member ที่มี implementation ภายใน interface ได้แล้ว โดยโค้ดด้านล่างเป็นการเขียน interface แบบเดิม

public interface ICalculator
{
    int Add(int a, int b);
}

จากโค้ดด้านบนเราจะเห็นว่ามันไม่สามารถมี implementation ภายใน method Add ได้ ส่วนโค้ดด้านล่างจะเห็นว่าเราสามารถใส่ implementation เข้าไปได้แล้ว

public interface ICalculator
{
    int Add(int a, int b)
    {
        return a + b;
    }
}

ความต่างของ interface กับ abstract กับจะเหลือเรื่อง multi inheritance เท่านั้นละ

🔥 More patterns in more places

ต่อยอดความสามารถของ C# version 7 เรื่องการทำ pattern matching ของคำสั่ง switch โดยมันมีความสามารถเพิ่มเข้ามาตามนี้เลย

💡 Switch expressions

เราสามารถย่อการทำงานของคำสั่ง switchให้มันสั้นลงได้แล้ว ยกตัวอย่างเช่นเราต้องทำงานกับ enum ที่มีค่าตามโค้ดล่างนี้

public enum MainColor
{
    Red,
    Green,
    Blue
}

ถ้าเป็นโค้ดแบบเดิมเราจะต้องเขียนการทำงานภายใน method เป็นแบบนี้

public static RGBColor FromMainColor(MainColor colorBand)
{
    switch (colorBand)
    {
        case Rainbow.Red:
            return new RGBColor(0xFF, 0x00, 0x00);
        case Rainbow.Green:
            return new RGBColor(0x00, 0xFF, 0x00);
        case Rainbow.Blue:
            return new RGBColor(0x00, 0x00, 0xFF);
        default:
            throw new ArgumentException();
    };
}

แต่ด้วยความสามารถใหม่เราจะสามารถย่อมันเข้ามาเป็นแบบนี้ได้

public static RGBColor FromMainColor(MainColor colorBand) =>
    colorBand switch
    {
        Rainbow.Red    => new RGBColor(0xFF, 0x00, 0x00),
        Rainbow.Green  => new RGBColor(0x00, 0xFF, 0x00),
        Rainbow.Blue   => new RGBColor(0x00, 0x00, 0xFF),
        _              => throw new ArgumentException(),
    };

💡 Property patterns

ถัดมาเราสามารถ map ค่าของ property ของ object ภายในคำสั่ง switch ได้เลย เช่นเรามีคลาส Address ที่เก็บรหัสจังหวัดไว้ใน property ที่ชื่อว่า State ดังนั้นเราก็สามารถเอา object ของ address มาใช้กับคำสั่ง switch ได้ตามด้านล่างเลย

public string GetStateCode(Address location) =>
    location switch
    {
        { State: "BKK" } => "10",
        { State: "KKN" } => "40",
        { State: "UBN" } => "76",
        _ => string.Empty
    };

💡 Tuple patterns

ความสามารถนี้ต่อยอดจากความสามารถของ C# version 7 เรื่อง tuple ซึ่งมันจะทำให้เราสามารถ map tuple เข้ากับคำสั่ง switch ได้แล้ว เช่นผมจะเขียนโค้ดในการตรวจว่าเกมเป่ายิงฉุบถ้าผลออกมาแบบนี้แล้วผลลัพท์จะเป็นแพ้ชนะหรือเสมอ โดยการส่ง string เข้าไป 2 ตัว เราก็สามารถใช้ความสามารถใหม่แบบเขียนเป็นแบบนี้ได้เลย

public string checkGameResult(string first, string second)
    => (first, second) switch
    {
        ("rock", "paper") => "Lose",
        ("rock", "scissors") => "Win",
        ("paper", "rock") => "Win",
        ("paper", "scissors") => "Lose",
        ("scissors", "rock") => "Lose",
        ("scissors", "paper") => "Win",
        (_, _) => "tie"
    };

💡 Positional patterns

จากความสามารถเดิมของ C# version 7 เราสามารถทำการจับคู่ระหว่างตำแหน่งของ deconstructor ของ object ได้ เช่นจากเดิมเวลาที่เราจับคู่เราจะต้องจับแบบนี้

public string Describe(object obj)
{
    switch(obj)
    {
        case Rectangle r when r.Length == 10 && r.Width == 10:
            return "Found 10x10 rectangle";
        ...
    }
}

แต่ด้วยความสามารถใหม่เราจะสามารถจับคู่แบบนี้ได้

public string Describe(object obj)
{
    switch(obj)
    {
        case Rectangle (10, 10): 
            return "Found 10x10 rectangle";
        ...
    }
}

💡 Recursive patterns

จากที่ว่ามาทั้งหมด เราสามารถเขียน pattern ที่ซ้อน pattern เข้าไปได้ด้วย ตามนี้เลย

switch( p.FirstName, p.MiddleName, p.LastName)
{
    case (string f, string m, string l):
        return $"{f} {m[0]}. {l}";
        
    case (string f, null, string l):
        return $"{f} {l}";
    ...
}

🔥 using declarations

แต่เดิมเราสามารถใช้คำสั่ง using เพื่อสร้างตัวแปรที่มันจะคืนทรัพยากรแบบอัตโนมัติเมื่อจบ block ของมันได้แล้ว ตามโค้ดด้านล่างเราจะเห็นว่า using แบบเดิมเมื่อ block ของมันจบลง ตัวแปรนั้นก็ทำการคืนทรัพยากรหลังจาก block ทันที

public void WriteSomeThing()
{
    using (var writer = new StreamWriter("file.txt"))
    {
        ...
    } // ตัวแปร writer จะเรียก Dispose ที่นี่
    ...
}

ด้วย C# version 8 เราสามารถสร้างตัวแปรที่มันอยู่ได้ตลอดภายใน block ที่มันอยู่ และจะคืนทรัพยากรเมื่อมันจบ block ของมันแล้วได้ ตามตัวอย่างด้านล่าง

public void WriteSomeThing()
{
    using var writer = new StreamWriter("file.txt");
    ...
    // ตัวแปร writer จะเรียก Dispose ที่นี่
}

🔥 Static local functions

ความสามารถใหม่ตัวนี้ต่อยอดจาด C# version 7 เราจะสามารถสร้าง local function ได้ แตมาใน version 8 นี้เราจะสามารถสร้าง local function ที่เป็น static ได้ โดยความสามารถใหม่นี้จะป้องกันไม่ให้เราเผลอไปเรียกใช้งานตัวแปรที่เป็นพวก local variable นั่นเอง ลองดูโค้ดด้านล่างนี้ที่เขียนด้วย local function ของ C# version 7 ซึ่งเราอาจจะเผลอไปเรียกใช้งาน local variable ได้

public void SomeMethod()
{
    int a = 7;
    
    void LocalFunction() => a = 0;
}

โค้ดด้านล่างคือความสามารถใหม่ที่เป็น static local function ซึ่งมันจะป้องกันไม่ให้เราไปเรียกใช้ local variable ได้เลย ซึ่งถ้าเผลอไปเรียกมันจะ compile ไม่ผ่านทันที

public void SomeMethod()
{
    int a = 7;
    
    static void LocalFunction(int b) => b = 0;
}

🔥 Disposable ref structs

ใน C# version 7 เขาได้เพิ่มความสามารถใหม่เข้ามานั่นคือคำสั่ง ref ซึ่งจะทำให้เราสามารถอ้างอิงของในรูปแบบ reference type ได้ ซึ่งจากไอเดียนี้เราก็จะสามารถสร้าง struct ที่เป็น ref ได้เช่นกันตามโค้ดด้านล่าง

ref struct Something
{
}

แต่ด้วยข้อจำกัดบางประการเลยทำให้เจ้า struct ไม่สามารถ implement interface ได้เลย ดังนั้นเวลาที่เราสร้าง struct ที่จำเป็นต้องคืนทรัพยากรหลังใช้งานเสร็จก็จะมีปัญหา เพราะเราจะไป implement IDisposable ไม่ได้นั่นเอง ทำให้มีโอกาสสูงที่จะลืมคืนทรัพยากร และ แน่นอนว่าคำสั่ง using ก็ไม่สามารถใช้ได้ด้วยนั่นเอง

จากที่เกริ่นมาทั้งหมดนั้นเจ้า C# version 8 ได้แก้ปัญหาให้ struct มีความสามารถใช้ Dispose ได้แล้วโดยที่ไม่ต้อง implement IDisposable เลย โดยแค่สร้าง method Dispose ให้เป็น public เพียงเท่านี้เอง ตามโค้ดด้านล่าง

ref struct Something
{
    public void Dispose()
    {
    }
}

ส่วนใครที่ต้องการเรียกใช้ struct ตัวนี้ก็สามารถใช้คำสั่ง using ลงไปดื้อๆได้เลยตามโค้ดด้านล่างนี้

using (var st = new Something())
{
    ...
}

🔥 Nullable reference types

เวลาที่เราทำงานกับ reference type นั้นมีบ่อยครั้งที่เราอาจเจอ error ประเภท NullReferenceException เด้งมาให้เห็นบ่อยๆ ดังนั้นใน C# version 8 นี้เขาได้เพิ่มการแจ้งเตือนแบบใหม่ขึ้นมา เพื่อแยกของต่างๆออกจากกันว่าข้อมูลตัวนี้เป็น null ได้ ตัวนี้ไม่มีทางเป็น null ซึ่งการแจ้งเตือนทั้งหมดจะแสดงผลผ่าน warning ออกมานั่นเอง ส่วนถ้าอยากเปิดการใช้การแจ้งเตือนแบบใหม่ เราจะต้องใส่แทก #nullable enable ตัวนี้เข้าไป เพื่อบอกว่าเราจะเปิดใช้งานการตรวจสอบ null แล้วนะตามโค้ดด้านล่าง

#nullable enable

ส่วนในการใช้งานเราจะต้องทำการระบุว่าตัวแปร reference type ไหนบ้างที่เป็น null ได้ โดยตัวแปรพวกนั้นก็จะใช้คำสั่ง ? ด้านหลัง data type เพื่อเป็นการประกาศว่ามันเป็น nullable นั่นเอง ตามโค้ดด้านล่างเลย

public class Student
{
    public string FirstName { get; set; }
    public string? LastName { get; set; } // เป็น null ได้
}

🔥 Asynchronous streams

จาก C# version 5 นั่นเราได้รู้จักกับคำสั่ง async กันไปแล้ว แต่ถ้าเราใช้งานเราจะพบว่ามันมีปัญหาในการทำงานเวลาที่เราจะค่อยๆส่งข้อมูลออกมาเรื่อยๆ ในลักษณะของ streaming ดังนั้นใน C# version 8 นี้เขาก็ได้แก้ปัญหานี้ให้เราแล้วโดยใช้คำสั่ง IAsyncEnumerable<T> นั่นเอง จากโค้ดด้านล่างผมจะส่งเลข 1-20 มาเป็น streaming ผมก็จะเขียนได้ว่า

public async IAsyncEnumerable<int> GenerateSequence()
{
    for(var i = 1; i <= 20; i++)
    {
        await Task.Delay(100);
        yield return i;
    }
}

ส่วนคนที่เรียกใช้ method นี้ก็สามารถใช้คำสั่ง await เพื่อทำงานร่วมกับคำสั่ง foreach ได้เลยด้วย ตามโค้ดด้านล่าง

await foreach (var number in GenerateSequence())
{
    Console.WriteLine(number);
}

🔥 Indices and ranges

ความสามารถใหม่ในการเข้าถึงข้อมูลที่เป็นตระกูล Array collection

💡 Indices

สมัยก่อนถ้าเราจะเข้าไปทำอะไรซักอย่างกับ Array แล้วล่ะก็ เราจะต้องเข้าถึงผ่านเจ้าตัวที่เรียกว่า indexer เช่น ขอเข้าถึงข้อมูลตัวแรก [0] หรือข้อมูลตัวที่ 3 [2] ประมาณนี้ แต่ด้วยความสามารถใหม่นี้เราจะมีตัวอ้างอิง Array collection แบบกลับหลังได้ด้วย ตามโค้ดด้านล่างนี้เลย

var words = new string[]
{
                // index from start    index from end
    "The",      // 0                   ^9
    "quick",    // 1                   ^8
    "brown",    // 2                   ^7
    "fox",      // 3                   ^6
    "jumped",   // 4                   ^5
    "over",     // 5                   ^4
    "the",      // 6                   ^3
    "lazy",     // 7                   ^2
    "dog"       // 8                   ^1
};              // 9 (words.Length)    ^0

จากโค้ดด้านบนจะเห็นว่าเราสามารถอ้างอิงข้อมูล Array collection แบบกลับหลังได้โดยใช้เครื่องหมาย ^ นั่นเอง เช่นผมอยากได้ข้อมูลตัวสุดท้ายก็จะเขียนออกมาแบบนี้ได้เลย

Console.WriteLine($"The last word is {words[^1]}");
// "dog"

💡 Ranges

นอกจากการเข้าถึง Array collection แบบใหม่แล้ว เขายังรองรับการทำงานกับ Array collection แบบเข้าถึงข้อมูลเป็นช่วงได้ด้วย เช่นผมอยากได้ข้อมูลตัวที่ 2 ถึงตัวที่ 4 นั่นก็คือ quick brown fox ผมก็สามารถเขียนโค้ดง่ายๆตามด้านล่างนี้เลย

var quickBrownFox = words[1..4];
// { quick, brown, fox }

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

var lazyDog = words[^2..^0];
// { lazy, dog }

และที่เจ๋งไปกว่านั้นของคำสั่ง .. ก็คือถ้าเราไม่ระบุว่าจะเอาข้อมูลจากไหนถึงไหน มันก็จะกวาดมาทั้งหมดเลย เหมือนกับคำสั่ง * ของพวก SQL นั่นเอง

var allWords = words[..]; // เอาข้อมูลมาทั้งหมดเลย
var firstPhrase = words[..4]; // เอาตั้งแต่ index แรกถึง index 4
var lastPhrase = words[6..]; // เอาตั้งแต่ index 6 ถึงตัวสุดท้าย

ยังไม่หมดเพียงเท่านี้ เรายังสามารถสร้างตัวแปรแบบ Range เก็บเอาไว้ใช้งานได้ด้วยนะ

Range phrase = 1..4;
var text = words[phrase];

🔥 Null-coalescing assignment

เวลาที่เราทำงานกับ reference type หรือ Nullable หรือพูดง่ายๆคือข้อมูลที่มันอาจจะเป็น null ได้ เราจะต้องคอยระวังเวลาใช้งานมันเสมอเพราะไม่งั้นจะได้ NullReferenceException โผล่มาจ๊ะเอ๋ได้ ดังนั้นเราอาจจะต้องตรวจค่ามันว่าเป็น null หรือเปล่าเพื่อป้องกันมันเป็น null ก่อนเรียกใช้งานราวๆนี้

IEnumerable<int> numbers = null;
if (numbers == null)
{
    numbers = Enumerable.Empty<int>();
}

แต่ด้วยความสามารถใหม่ของ C# version 8 เราสามารถใช้คำสั่ง ??= เพื่อเป็นการบอกว่า ถ้าค่าด้านซ้ายเป็น null ให้เอาค่าด้านขวาไปกำหนดให้ค่าด้านซ้ายได้เลย แต่ถ้าไม่เป็น null ให้ข้ามไป ดังนั้นโค้ดใหม่เราก็จะออกมาเหลือเพียงแค่นี้

IEnumerable<int> numbers = null;
numbers ??= Enumerable.Empty<int>();

🔥 Unmanaged constructed types

ตั้งแต่ C# version 7.3 ลงมานั้นตัว constructed type จะไม่สามารถเป็น unmanaged type ได้ แต่ในตัว C# version 8 นั้นถ้า construct value นั้นมีแต่ members ที่เป็น unmanaged types แล้วล่ะก็ตัวมันก็จะเป็น unmanaged เช่นกัน เช่นผมมี constructed type ตัวนึงตามโค้ดด้านล่างนี้

public struct Coords<T>
{
    public T X;
    public T Y;
}

แล้วผมไปทำการสร้าง Coords โดยส่ง T เป็น unmanaged types เช่น Coords<int> Coords<bool> บลาๆ ซึ่งภายในของ Coords นั้นมีแต่ unmanged types อย่างเดียว ผมก็จะสามารถใช้ pointer หรือ stackalloc ไปเล่นกับมันได้นั่นเอง

Span<Coords<int>> coordinates = stackalloc[]
{
    new Coords<int> { X = 0, Y = 0 },
    new Coords<int> { X = 0, Y = 3 },
    new Coords<int> { X = 4, Y = 0 }
};

ปรกติผมไม่ได้เล่นกับ pointer มานักถ้าสนใจก็สามารถไปศึกษาเพิ่มเติมได้จากลิงค์ด้านล่างนี้ครับ

🔥 Enhancement of interpolated verbatim strings

หลังจากที่ C# version 7 ได้นำเสนอความสามารถในการสร้างตัวอักษรแบบใหม่ด้วยเครื่องหมาย $ กันแล้ว ถ้าเพื่อนๆหลายๆคนได้ลองใช้คู่กับเจ้าเครื่องหมาย @ นี้แล้วละก็จะพบว่า มันทำงานร่วมกันไม่ได้ แต่ตอนนี้ C# version 8 ก็ได้ออกมาแก้ไขให้มันสามารถใช้งานร่วมกันได้แล้ว เย่ๆ โดยจะเอาอันไหนขึ้นก่อนขึ้นหลังก็ได้ครับ ตามตัวอย่างด้านล่างเลย

 var fileName = test.jpg;
 var path1 = $@"c:\{filename}";
 var path2 = @$"c:\{filename}";

🎥 วีดีโอประกอบความเข้าใจ

PreviousTipsNextBoxing & Unboxing

Last updated 5 years ago

Was this helpful?

👶
💡
💡
Microsoft Document - Stackalloc
Microsoft Document - Unmanaged types