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
  • 😢 ปัญหา
  • 😄 วิธีแก้ปัญหา
  • 🔥 Action
  • 🔥 Func
  • 💡 Anonymous
  • Delegate
  • Lambda
  • 🤔 ทำไมต้องใช้ของพวกนี้ด้วย ?

Was this helpful?

Export as PDF
  1. มือใหม่หัดเขียนโค้ด
  2. เขียนโค้ดด้วยภาษา C#
  3. ⏳ระดับสูง

Action & Func

PreviousDelegatesNextLambda expression

Last updated 5 years ago

Was this helpful?

😢 ปัญหา

ทุกครั้งที่เราจะทำงานกับ delegate มันวุ่นวาย เพราะเราต้องสร้าง delegate ที่มี signature ที่อยากได้ก่อนเสมอถึงจะเริ่มใช้งานมันได้ มีวิธีไหนที่ทำงานกับมันได้ง่ายๆอีกไหม ?

ถ้าอ่านแล้ว งงๆ ผมขอยกตัวอย่างว่า สมมุติผมอยากมีจะเก็บ method ในโค้ดด้านล่างนี้

static void AwesomeMethod()
{
    Console.WriteLine("Hello world");
}

ไว้ในตัวแปรซักตัว ผมก็ต้องสร้าง delegate ขึ้นมาก่อน ตามนี้

delegate void SALADPUK_DELEGATE();

พอมีโค้ดด้านบนละ เราก็ถึงจะเริ่มไปสร้างตัวแปรมาเก็บ method AwesomeMethod ได้นั่นเอง ตามโค้ดด้านล่าง

static void Main(string[] args)
{
    SALADPUK_DELEGATE d = AwesomeMethod;
    d();  // Hello world
}

ซึ่งปัญหาคือถ้าจะทำแบบนี้เราก็ต้องไปสร้าง delegate ทุกครั้งเลยใช่ไหม ? มีง่ายกว่านี้ไหม?

แนะนำให้อ่าน หากยังไม่ได้อ่านเรื่อง delegate จงไปอ่านก่อนซะ ไม่นานหรอก

😄 วิธีแก้ปัญหา

การแก้ปัญหาสั้นสุดแสนจะง่าย เพราะใน C# เขาได้เตรียมสิ่งที่เรียกว่า Action กับ Func มาให้เราเล่นแล้วยังไงล่ะ ดังนั้นไปดูกันทีละตัวเลยละกันนะ

🔥 Action

สมมุติว่าเราอยากเก็บ method ไว้ในตัวแปรซักตัว เราก็สามารถใช้ Action ไปเก็บเจ้า method นั้นได้เลย แต่เงื่อนไขคือเจ้า method ที่จะเก็บลงใน Action ได้นั้น มันจะต้องมี return type เป็น void เท่านั้นนะจ๊ะ

เช่น ผมต้องการจะเก็บ method ด้านล่างนี้ไว้ในตัวแปรซักตัว

static void AwesomeMethod()
{
    Console.WriteLine("Hello world");
}

เราก็สามารถสร้าง Action มาเก็บมันได้เลย เห็นมะเรียบง่ายดี ไม่ต้องสร้าง delegate ให้วุ่นวาย

static void Main(string[] args)
{
    Action a = AwesomeMethod;
    a();
}

แบบรองรับ parameters

หรือถ้าเราอยากเก็บ method ที่มี parameter เอาไว้ในตัวแปรบ้างล่ะ เช่น ในโค้ดด้านล่าง

static void CalculatorMethod(int a, int b, int c)
{
    var result = a + b + c;
    Console.WriteLine($"The result is: {result}");
}

เราก็สามารถสร้าง Action ที่มี signature ตรงกับ method ของเราได้เช่นกัน โดยการใช้ Generic เข้ามาช่วย ตามโค้ดด้านล่าง

static void Main(string[] args)
{
    Action<int, int, int> a = CalculatorMethod;
    a(1, 5, 7);
}

🔥 Func

หลังจากที่เราเห็น action ไปเรียบร้อยละ คราวนี้ก็จะเป็นคราวของ Func บ้าง ซึ่งสิ่งที่มันทำได้นั้นก็จะเหมือนกับ action เลย ต่างกันแค่ มันเอาไว้เก็บ method ที่มี return type นั่นเอง

เช่นผมต้องการจะเก็บ method ตัวนี้ไว้ในตัวแปรซักตัว

static double Add(int first, int second)
{
    var result = first + second;
    return result;
}

สิ่งที่เราต้องทำก็คือ ทำการสร้าง Func ที่มี signature ตรงกับ method ที่เราต้องการจะเก็บค่ามันไว้นั่นเอง ตามโค้ดด้านล่าง

static void Main(string[] args)
{
    Func<int, int, double> f = Add;
    var result = f(5, 9);
    Console.WriteLine(result);
}

อธิบายโค้ดด้านบนนิดหน่อย เจ้า Func ก็เหมือนกับ Action แหละ ต่างกันแค่ตัวตัว Generic ตัวสุดท้ายของมันจะต้องเป็น return type ของ method นั่นเอง ซึ่งเจ้า method Add มี return type เป็น double ดังนั้นเลยทำให้ Func ของเราจะต้องมี Generic ตัวสุดท้ายเป็น double ด้วยนั่นเอง

💡 Anonymous

ในการเขียนโค้ดบางทีเราก็อยากได้ method ใหม่ แต่ไม่อยากเขียน method นั้นไว้ในคลาส เพราะมันจะทำให้คลาสของเรารกใช่ป่ะ ดังนั้นเราก็สามารถสร้าง method ในรูปแบบที่เรียกว่า anonymous ได้ครับ ซึ่งมันทำได้หลายแบบเลย ตามนี้

Delegate

เป็นการสร้าง anonymous method โดยการใช้ delegate เข้ามาช่วย

คำแนะนำ วิธีการนี้เราจะไม่ค่อยได้เห็นแล้วนะ เพราะส่วนใหญ่เราจะใช้ Lambda แทนแล้วครับ แต่แค่อยากให้รู้ว่ามันก็เขียนแบบนี้ได้นะ เพราะในสมัยก่อนที่ C# 3.0 ยังไม่ออก เรายังไม่มี lambda มาใช้ยังไงล่ะ

สมมุติว่าผมอยากได้ method ซักตัว ที่มันทำงานแบบโค้ดตัวนี้

static void Add(int first, int second)
{
    var result = first + second;
    Console.WriteLine(result);
}

เราก็สามารถใช้ delegate ร่วมกับ Action ได้ครับ ก็จะได้ออกมาเป็นแบบนี้

static void Main(string[] args)
{
    Action<int, int> a = delegate (int first, int second)
    {
        var result = first + second;
        Console.WriteLine(result);
    };
    a(5, 9);
}

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

Lambda

เป็นการสร้าง anonymous method โดยการใช้ lambda เข้ามาช่วย ซึ่งเราจะพบโค้ดลักษณะนี้บ่อยมากถึงมากที่สุดในการเขียน C# ครับ

สมมุติว่าผมอยากได้ method ซักตัว ที่มันทำงานแบบโค้ดตัวนี้

static void Add(int first, int second)
{
    var result = first + second;
    Console.WriteLine(result);
}

เราก็สามารถใช้ lambda ร่วมกับ Action ได้ครับ ก็จะได้ออกมาเป็นแบบนี้

static void Main(string[] args)
{
    Action<int, int> a = (first, second)=>
    {
        var result = first + second;
        Console.WriteLine(result);
    };
    a(5, 9);
}

🤔 ทำไมต้องใช้ของพวกนี้ด้วย ?

หลายๆคนอาจจะเริ่มมีคำถามว่า ทำไมไม่เรียกใช้ method มันไปตรงๆเลยล่ะ จะมามัวเก็บเป็นตัวแปรไว้ทำไมใช่ป่ะ

คำตอบก็คือ ใช่ครับเราไม่ต้องใช้ของพวกนี้เลยก็ได้เพราะเราเรียกใช้ method ได้เลยสะดวกดี แต่ในบางสถานะการณ์ ถ้าเราไม่ใช้ความสามารถของพวกนี้มันจะทำให้เราทำงานลำบากมาก ยกตัวอย่างเช่น เราอยากจะให้โปรแกรมของเราไปทำงาน A ให้เสร็จก่อน และเมื่อมันทำงานเสร็จแล้ว ค่อยกลับมาเรียกใช้งาน B ต่อนะ ซึ่งเราเรียกลักษณะการทำงานแบบนี้ว่า Callback ครับ ดังนั้นมาดูกันว่าการใช้ action หรือ func มาช่วยเรื่องการทำ callback นั้นมันจะช่วยแก้ปัญหานี้ได้ยังไงกัน

สมมุติว่าผมมีคลาสตัวนึงที่มี method 2 อัน

static void A()
{
    Console.WriteLine("A");
}

static void B()
{
    Console.WriteLine("B");
}

ซึ่งผมต้องการให้มันทำงาน method A เสร็จก่อน แล้วค่อยเรียกใช้ method B เราจะทำยังไง? สมมุติว่าการทำงานของ A มันเป็น asynchronous

Asynchronous & Synchronous โดยปรกติโค้ดที่เราเขียนอยู่นั้นมันจะทำงานในลักษณะที่เรียกว่า Synchronous ซึ่งมันจะรอจนกว่าโค้ดบรรทัดนั้นจะทำงานจนเสร็จถึงจะไปทำงานบรรทัดอื่นต่อ แต่การทำงานของ Asynchronous จะตรงกันข้ามกัน คือมันจะไม่รอ เมื่อสั่งทำงานโค้ดที่เป็น asynchronous ไปละ มันก็จะไปทำงานบรรทัดต่อไปเลย

ซึ่งในตัวอย่างคือถ้าเราเรียกใช้งาน method A ปุ๊ป มันก็จะไปทำงานอย่างอื่นต่อ ไม่รอให้ method A ทำงานจนเสร็จ ดังนั้นถ้าเราเรียก method B ต่อจากการเรียก method A มันจะมีโอกาสทำงาน A กับ B พร้อมกันได้ ซึ่งทำให้ลำดับการทำงานไม่ตรงตามที่เราต้องการนั่นเอง

คำตอบก็คือ เราก็แค่ส่ง method B เข้าไปเป็น parameter ของ method A ยังไงล่ะ ซึ่งพอ method A ทำงานเสร็จ มันก็จะเรียกใช้ method B ต่อเลยนั่นเอง ดังนั้นโค้ดเราก็จะออกมาเป็นภาพนี้

static void A(Action callback)
{
    Console.WriteLine("A");
    callback();
}

static void B()
{
    Console.WriteLine("B");
}

แนะนำให้อ่าน ใครยังไม่ได้อ่านเรื่อง Generic แนะนำให้ไปอ่านซะเพราะหลังๆเราจะใช้มันบ่อยมาก จนเรียกว่าไม่รู้จักมันแล้วละก็ชีวิตจะวุ่นวายขึ้นเยอะเลยเวลาเขียน C#

แนะนำให้อ่าน Lambda คืออะไรสามารถอ่านได้จากบทความนี้ครัช

👶
👨
Saladpuk - Delegates
Saladpuk - Generic
Saladpuk - Lambda expression