0Pricing
C# Academy · บทเรียน

โคลเชอร์และตัวแปรที่ถูกจับค่า

ดูว่าฟังก์ชันภายในจับสถานะไว้อย่างไร

โคลเชอร์และตัวแปรที่ถูกจับค่า เป็นบทเรียน C# Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C# Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C# Academy มีบทเรียนทั้งหมด 4 บทเรียน

คลอเชอร์เหนือสถานะภายใน

ฟังก์ชันภายในหรือแลมบ์ดาสามารถอ่านและแก้ไขตัวแปรจากเมธอดที่ครอบอยู่ได้ การทำเช่นนี้เรียกว่า การจับตัวแปร และฟังก์ชันรวมกับตัวแปรที่จับไว้จะเรียกว่า คลอเชอร์

การจับตัวแปร

ฟังก์ชันภายในใช้ factor จากเมธอดที่ครอบอยู่โดยตรง ฟังก์ชันไม่ได้รับค่าดังกล่าวเป็นพารามิเตอร์ แต่จับค่าจากขอบเขตโดยรอบ

using System;

public class Program
{
    public static void Main()
    {
        int factor = 3;
        int Scale(int n) => n * factor; // captures factor

        Console.WriteLine(Scale(5));
        Console.WriteLine(Scale(10));
    }
}

ตัวแปรที่ถูกจับเป็นการอ้างอิงที่มีการเปลี่ยนแปลงได้

คลอเชอร์จะจับตัวแปร ไม่ใช่ภาพบันทึกค่าของตัวแปร หากตัวแปรเปลี่ยนค่าหลังจากกำหนดฟังก์ชันแล้ว ฟังก์ชันจะเห็นค่าใหม่

using System;

public class Program
{
    public static void Main()
    {
        int offset = 10;
        int Add(int n) => n + offset;

        Console.WriteLine(Add(1)); // 11
        offset = 100;
        Console.WriteLine(Add(1)); // 101 - sees updated offset
    }
}

การแก้ไขตัวแปรที่ถูกจับ

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

using System;

public class Program
{
    public static void Main()
    {
        int count = 0;
        void Tick() => count++;

        Tick(); Tick(); Tick();
        Console.WriteLine(count); // 3
    }
}

การส่งกลับคลอเชอร์

เมื่อคุณส่งกลับแลมบ์ดาที่จับตัวแปรภายในไว้ ตัวแปรเหล่านั้นจะมีอายุยืนกว่าเมธอด สถานะที่ถูกจับจะคงอยู่ตราบเท่าที่ดีลีเกตยังคงอยู่

using System;

public class Program
{
    static Func<int> MakeCounter()
    {
        int count = 0;
        return () => ++count; // captures count
    }

    public static void Main()
    {
        var next = MakeCounter();
        Console.WriteLine(next());
        Console.WriteLine(next());
        Console.WriteLine(next());
    }
}

คลอเชอร์ที่เป็นอิสระต่อกัน

การเรียกใช้โรงงานสร้างแต่ละครั้งจะสร้างชุดตัวแปรที่ถูกจับชุดใหม่ ตัวนับสองตัวที่สร้างด้วยวิธีนี้จะไม่รบกวนกัน

using System;

public class Program
{
    static Func<int> MakeCounter()
    {
        int count = 0;
        return () => ++count;
    }

    public static void Main()
    {
        var a = MakeCounter();
        var b = MakeCounter();
        Console.WriteLine(a()); // 1
        Console.WriteLine(a()); // 2
        Console.WriteLine(b()); // 1 - separate state
    }
}

การแก้ปัญหาการจับตัวแปรในลูป foreach

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

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        var actions = new List<Action>();
        foreach (var i in new[] { 1, 2, 3 })
            actions.Add(() => Console.WriteLine(i));

        foreach (var act in actions) act(); // prints 1, 2, 3
    }
}

การจับตัวแปรในลูป for

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

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        var actions = new List<Action>();
        for (int i = 0; i < 3; i++)
        {
            int copy = i; // fresh local each iteration
            actions.Add(() => Console.WriteLine(copy));
        }
        foreach (var act in actions) act(); // prints 0, 1, 2
    }
}

คลอเชอร์จับการอ้างอิง ไม่ใช่ค่า

เนื่องจากการจับตัวแปรเป็นการจับด้วยการอ้างอิง คลอเชอร์จึงมองเห็นการแก้ไขค่าต้นฉบับหลังการจับตัวแปร โปรดจำเรื่องนี้ไว้เมื่อจังหวะการอ่านและการเขียนมีความสำคัญ

using System;

public class Program
{
    public static void Main()
    {
        string message = "first";
        Action print = () => Console.WriteLine(message);

        print();          // first
        message = "second";
        print();          // second
    }
}

การใช้งานจริง: ลักษณะการทำงานที่กำหนดค่าได้

คลอเชอร์ช่วยให้คุณสร้างฟังก์ชันขนาดเล็กที่เตรียมบริบทไว้ล่วงหน้าได้ ในที่นี้ ฟังก์ชันส่วนลดจะจับอัตราส่วนลดไว้ ทำให้ได้เครื่องคำนวณที่กำหนดค่าแล้วและนำกลับมาใช้ได้

using System;

public class Program
{
    static Func<double, double> MakeDiscount(double rate)
        => price => price * (1 - rate);

    public static void Main()
    {
        var tenOff = MakeDiscount(0.10);
        var halfOff = MakeDiscount(0.50);
        Console.WriteLine(tenOff(100));
        Console.WriteLine(halfOff(100));
    }
}

ลองทำด้วยตนเอง

สร้างโรงงานสร้างตัวนับที่คลอเชอร์ที่ส่งกลับมารักษาสถานะส่วนตัวไว้ จากนั้นสร้างตัวนับที่เป็นอิสระต่อกันสองตัวจากโรงงานนั้น

using System;

public class Program
{
    static Func<int> MakeStepper(int step)
    {
        int current = 0;
        return () => { current += step; return current; }; // captures current and step
    }

    public static void Main()
    {
        var byTwos = MakeStepper(2);
        var byTens = MakeStepper(10);
        Console.WriteLine(byTwos()); // 2
        Console.WriteLine(byTwos()); // 4
        Console.WriteLine(byTens()); // 10 - separate state
    }
}

ตรวจสอบอย่างรวดเร็ว

วิเคราะห์ว่าการจับตัวแปรทำงานอย่างไร

สรุปทบทวน

คลอเชอร์จับตัวแปรที่อยู่ในขอบเขตโดยรอบด้วยการอ้างอิง

  • ฟังก์ชันจะเห็นค่าปัจจุบันของตัวแปร รวมถึงการเปลี่ยนแปลงที่เกิดขึ้นภายหลัง
  • ฟังก์ชันสามารถแก้ไขตัวแปรที่ถูกจับและใช้สถานะร่วมกับเมธอดได้
  • คลอเชอร์ที่ส่งกลับมาจะทำให้ตัวแปรที่ถูกจับยังคงอยู่
  • ใช้ตัวแปรภายในของแต่ละรอบในลูป for เพื่อจับค่าที่แตกต่างกัน

คำถามที่พบบ่อย

บทเรียน “โคลเชอร์และตัวแปรที่ถูกจับค่า” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “โคลเชอร์และตัวแปรที่ถูกจับค่า” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C# Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C# Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “โคลเชอร์และตัวแปรที่ถูกจับค่า”

ดูว่าฟังก์ชันภายในจับสถานะไว้อย่างไร คุณปฏิบัติ C# Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C# Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน C# Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “โคลเชอร์และตัวแปรที่ถูกจับค่า” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน C# Academy นี้ได้ไหม

ได้ บทเรียน C# Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การประกาศฟังก์ชันภายใน
  2. โคลเชอร์และตัวแปรที่ถูกจับค่า
  3. ฟังก์ชันภายในแบบสแตติก
  4. ฟังก์ชันภายในเทียบกับแลมบ์ดา
← กลับไปที่ C# Academy