ฉันเคยเห็นรูปแบบนี้ใน MSDN: yield break
แต่ฉันไม่รู้ว่ามันทำอะไร มีใครรู้บ้าง
MyList.Add(...)
yield return ...
หากคุณต้องการแยกวงออกก่อนเวลาอันควรและคืนรายการสำรองเสมือนที่คุณใช้yield break;
ฉันเคยเห็นรูปแบบนี้ใน MSDN: yield break
แต่ฉันไม่รู้ว่ามันทำอะไร มีใครรู้บ้าง
MyList.Add(...)
yield return ...
หากคุณต้องการแยกวงออกก่อนเวลาอันควรและคืนรายการสำรองเสมือนที่คุณใช้yield break;
คำตอบ:
มันระบุว่าตัววนซ้ำสิ้นสุดลงแล้ว คุณสามารถคิดว่าyield break
เป็นreturn
คำสั่งที่ไม่ส่งคืนค่า
ตัวอย่างเช่นหากคุณกำหนดฟังก์ชั่นเป็นตัววนซ้ำเนื้อความของฟังก์ชันอาจมีลักษณะดังนี้:
for (int i = 0; i < 5; i++)
{
yield return i;
}
Console.Out.WriteLine("You will see me");
โปรดทราบว่าหลังจากวนรอบเสร็จสิ้นรอบทั้งหมดบรรทัดสุดท้ายจะถูกเรียกใช้งานและคุณจะเห็นข้อความในแอปคอนโซลของคุณ
หรือเช่นนี้กับyield break
:
int i = 0;
while (true)
{
if (i < 5)
{
yield return i;
}
else
{
// note that i++ will not be executed after this
yield break;
}
i++;
}
Console.Out.WriteLine("Won't see me");
ในกรณีนี้คำสั่งสุดท้ายจะไม่ดำเนินการเพราะเราออกจากฟังก์ชั่นก่อน
break
แทนyield break
ในตัวอย่างของคุณไป? คอมไพเลอร์ไม่ได้บ่นเรื่องนั้น
break
ในกรณีนี้จะหยุดวง แต่มันจะไม่ยกเลิกการดำเนินการวิธีการดังนั้นบรรทัดสุดท้ายจะถูกดำเนินการและ "จะไม่เห็นฉันข้อความ" จะเห็นจริง
NullReferenceException
รับตัวแจงนับของ IEnumerable ได้ในขณะที่การหยุดรับผลตอบแทนนั้นคุณไม่มี (มีอินสแตนซ์ที่ไม่มีองค์ประกอบ)
yield return x
คอมไพเลอร์เตือนคุณต้องการให้เมธอดนี้เป็นน้ำตาล syntactic เพื่อสร้างEnumerator
วัตถุ แจงนับนี้มีวิธีการและทรัพย์สินMoveNext()
Current
MoveNext () ดำเนินการวิธีการจนกว่าจะมีคำสั่งและเปลี่ยนค่าที่เป็นyield return
Current
ครั้งต่อไปที่เรียกว่า MoveNext การดำเนินการจะดำเนินต่อจากที่นั่น yield break
ตั้งค่าปัจจุบันเป็นโมฆะส่งสัญญาณการสิ้นสุดของตัวแจงนับเพื่อที่foreach (var x in myEnum())
จะสิ้นสุด
สิ้นสุดบล็อกตัววนซ้ำ (เช่นบอกว่าไม่มีองค์ประกอบอีกต่อไปใน IEnumerable)
yield
คำหลักคุณสามารถทำซ้ำคอลเลกชันได้ทั้งสองทิศทางยิ่งไปกว่านั้นคุณสามารถใช้องค์ประกอบทุกอย่างของคอลเลคชั่นต่อไปไม่ได้อยู่ในแถวเดียวกันได้
yield
ทำมัน ฉันไม่ได้บอกว่าคุณผิดฉันเห็นสิ่งที่คุณแนะนำ แต่ในเชิงวิชาการไม่มีตัววนซ้ำใน. NET มีเพียงตัวแจงนับ (ทิศทางเดียวไปข้างหน้า) - ซึ่งแตกต่างจาก stdc ++ ไม่มี "กรอบตัววนซ้ำทั่วไป" ที่กำหนดไว้ใน CTS / CLR LINQ ช่วยปิดช่องว่างด้วยวิธีการส่วนขยายที่ใช้yield return
และวิธีการโทรกลับแต่เป็นวิธีส่วนขยายชั้นหนึ่งไม่ใช่ตัววนซ้ำชั้นหนึ่ง ผลลัพธ์IEnumerable
ไม่สามารถวนซ้ำไปในทิศทางอื่นนอกจากการส่งต่อผู้โทร
บอกตัววนซ้ำว่าถึงจุดสิ้นสุด
ตัวอย่างเช่น:
public interface INode
{
IEnumerable<Node> GetChildren();
}
public class NodeWithTenChildren : INode
{
private Node[] m_children = new Node[10];
public IEnumerable<Node> GetChildren()
{
for( int n = 0; n < 10; ++n )
{
yield return m_children[ n ];
}
}
}
public class NodeWithNoChildren : INode
{
public IEnumerable<Node> GetChildren()
{
yield break;
}
}
yield
โดยทั่วไปจะทำให้IEnumerable<T>
วิธีการทำงานในลักษณะคล้ายกันกับด้าย (กำหนดไว้ล่วงหน้า)
yield return
เป็นเหมือนเธรดที่เรียกใช้ฟังก์ชัน "schedule" หรือ "sleep" เพื่อยกเลิกการควบคุม CPU เช่นเดียวกับเธรดIEnumerable<T>
เมธอดจะควบคุมอีกครั้งที่จุดทันทีหลังจากนั้นตัวแปรโลคัลทั้งหมดที่มีค่าเดียวกับที่เคยมีก่อนที่จะถูกควบคุม
yield break
เป็นเหมือนเธรดที่ถึงจุดสิ้นสุดของฟังก์ชันและสิ้นสุด
ผู้คนพูดถึง "เครื่องรัฐ" แต่เครื่องรัฐเป็น "เกลียว" ทั้งหมดจริงๆ เธรดมีสถานะบางอย่าง (ค่า Ie ของตัวแปรโลคัล) และแต่ละครั้งที่มีการกำหนดเวลาไว้จะต้องดำเนินการบางอย่างเพื่อให้ได้สถานะใหม่ จุดสำคัญเกี่ยวกับการyield
ที่ไม่เหมือนกับเธรดระบบปฏิบัติการที่เราคุ้นเคยรหัสที่ใช้จะถูกตรึงในเวลาจนกว่าการวนซ้ำนั้นจะเป็นขั้นสูงหรือสิ้นสุดด้วยตนเอง
เรื่องทั้งหมดของบล็อก iterator ถูกปกคลุมอย่างดีในเรื่องนี้บทตัวอย่างฟรีจากจอน Skeet หนังสือC # ในความลึก
yield break
คำสั่งที่ทำให้เกิดการแจงนับหยุด มีผลบังคับใช้yield break
ทำการแจงนับโดยไม่ต้องส่งคืนรายการเพิ่มเติมใด ๆ
พิจารณาว่าจริงๆแล้วมีสองวิธีที่วิธีการวนซ้ำสามารถหยุดการวนซ้ำได้ ในกรณีหนึ่งตรรกะของวิธีการสามารถออกจากวิธีการตามธรรมชาติหลังจากกลับรายการทั้งหมด นี่คือตัวอย่าง:
IEnumerable<uint> FindPrimes(uint startAt, uint maxCount)
{
for (var i = 0UL; i < maxCount; i++)
{
startAt = NextPrime(startAt);
yield return startAt;
}
Debug.WriteLine("All the primes were found.");
}
ในตัวอย่างข้างต้นวิธี iterator จะหยุดดำเนินการตามธรรมชาติเมื่อmaxCount
พบช่วงเวลา
yield break
คำสั่งเป็นวิธีการที่ iterator เพื่อยุติแจงอีก มันเป็นวิธีที่จะแยกออกจากการแจงนับก่อน นี่เป็นวิธีเดียวกันกับข้างบน เวลานี้เมธอดมีข้อ จำกัด เกี่ยวกับระยะเวลาที่เมธอดสามารถดำเนินการได้
IEnumerable<uint> FindPrimes(uint startAt, uint maxCount, int maxMinutes)
{
var sw = System.Diagnostics.Stopwatch.StartNew();
for (var i = 0UL; i < maxCount; i++)
{
startAt = NextPrime(startAt);
yield return startAt;
if (sw.Elapsed.TotalMinutes > maxMinutes)
yield break;
}
Debug.WriteLine("All the primes were found.");
}
yield break
ขอให้สังเกตการเรียกร้องให้ ผลก็คือออกจากการแจงนับก่อน
แจ้งให้ทราบล่วงหน้าเกินไปว่าทำงานแตกต่างกันมากกว่าเพียงแค่ธรรมดาyield break
break
ในตัวอย่างข้างต้นออกมาจากวิธีการโดยไม่ทำให้การเรียกร้องให้yield break
Debug.WriteLine(..)
ที่นี่http://www.alteridem.net/2007/08/22/the-yield-statement-in-c/เป็นตัวอย่างที่ดีมาก:
สาธารณะแบบคงที่ IEnumerable <int> ช่วง (int min, int max) { ในขณะที่ (จริง) { if (min> = max) { ทำลายผลผลิต; } ผลตอบแทนคืนขั้นต่ำ ++; } }
และคำอธิบายว่าถ้าyield break
คำสั่งถูกตีภายในเมธอดการดำเนินการของเมธอดนั้นจะหยุดโดยไม่มีการส่งคืน มีบางเวลาที่สถานการณ์เมื่อคุณไม่ต้องการให้ผลลัพธ์ใด ๆ จากนั้นคุณสามารถใช้ตัวแบ่งผลตอบแทน
การหยุดรับผลตอบแทนเป็นเพียงวิธีการบอกผลตอบแทนเป็นครั้งสุดท้ายและไม่คืนค่าใด ๆ
เช่น
// returns 1,2,3,4,5
IEnumerable<int> CountToFive()
{
yield return 1;
yield return 2;
yield return 3;
yield return 4;
yield return 5;
yield break;
yield return 6;
yield return 7;
yield return 8;
yield return 9;
}
หากสิ่งที่คุณหมายถึงโดย "สิ่งที่ทำให้ผลตอบแทนที่แท้จริงทำ" คือ "มันทำงานอย่างไร" - ดูบล็อกของ Raymond Chen สำหรับรายละเอียดhttps://devblogs.microsoft.com/oldnewthing/20080812-00/?p=21273
ตัววนซ้ำ C # สร้างโค้ดที่ซับซ้อนมาก
คีย์เวิร์ด yield ใช้พร้อมกับคีย์เวิร์ด return เพื่อจัดเตรียมค่าให้กับอ็อบเจ็กต์ตัวแจงนับ ผลตอบแทนผลตอบแทนระบุค่าหรือค่าผลตอบแทน เมื่อถึงคำสั่งคืนผลตอบแทนที่ตั้งปัจจุบันจะถูกเก็บไว้ การดำเนินการจะเริ่มต้นใหม่จากตำแหน่งนี้ในครั้งต่อไปที่มีการเรียกตัววนซ้ำ
ในการอธิบายความหมายโดยใช้ตัวอย่าง:
public IEnumerable<int> SampleNumbers() { int counter = 0; yield return counter; counter = counter + 2; yield return counter; counter = counter + 3; yield return counter ; }
ค่าที่ส่งคืนเมื่อมีการทำซ้ำคือ: 0, 2, 5
สิ่งสำคัญคือให้สังเกตว่าตัวแปรตัวนับในตัวอย่างนี้เป็นตัวแปรท้องถิ่น หลังจากการวนซ้ำครั้งที่สองซึ่งส่งคืนค่า 2 การวนซ้ำครั้งที่สามเริ่มต้นจากที่เหลือก่อนหน้าขณะที่รักษาค่าก่อนหน้าของตัวแปรโลคอลที่ชื่อว่าตัวนับซึ่งเป็น 2
yield break
ไม่
yield return
จริง ๆ แล้วสนับสนุนการคืนค่าหลายค่า บางทีนั่นอาจไม่ใช่สิ่งที่คุณตั้งใจจริงๆ แต่นั่นเป็นวิธีที่ฉันอ่าน
yield break
มันไม่มีตัวแจงนับระดับภาษาเช่นforeach
- เมื่อใช้ตัวแจงนับyield break
จะให้ค่าจริง ตัวอย่างนี้ดูเหมือนว่าลูปที่ไม่ได้ควบคุม คุณแทบจะไม่เคยเห็นรหัสนี้ในโลกแห่งความเป็นจริง (เราทุกคนสามารถนึกถึงกรณีขอบบางอย่างแน่นอน) และยังไม่มี "ตัววนซ้ำ" ที่นี่ "iterator block" ไม่สามารถขยายเกินกว่าวิธีการเป็นข้อกำหนดของภาษา สิ่งที่ส่งคืนจริง ๆ คือ "นับได้" ดูเพิ่มเติมได้ที่: stackoverflow.com/questions/742497//