โคลเชอร์และตัวแปรที่ถูกจับค่า
ดูว่าฟังก์ชันภายในจับสถานะไว้อย่างไร
โคลเชอร์และตัวแปรที่ถูกจับค่า เป็นบทเรียน 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การประกาศฟังก์ชันภายใน
- โคลเชอร์และตัวแปรที่ถูกจับค่า
- ฟังก์ชันภายในแบบสแตติก
- ฟังก์ชันภายในเทียบกับแลมบ์ดา