yield
শব্দ আপনি একটি তৈরি করার অনুমতি দেয় IEnumerable<T>
একটি অন আকারে পুনরুক্তিকারীর ব্লক । এই পুনরুক্তিকারী ব্লকটি স্থগিত কার্যকরকরণকে সমর্থন করে এবং আপনি যদি ধারণার সাথে পরিচিত না হন তবে এটি প্রায় যাদুতে প্রদর্শিত হতে পারে। যাইহোক, দিনের শেষে এটি কেবল কোড যা কোনও অদ্ভুত কৌশল ছাড়াই কার্যকর করে।
একটি পুনরাবৃত্তকারী ব্লককে সিনট্যাকটিক চিনি হিসাবে বর্ণনা করা যেতে পারে যেখানে সংকলক একটি রাষ্ট্রীয় মেশিন তৈরি করে যা গণনার সংখ্যাটি কতদূর এগিয়ে গেছে তা ট্র্যাক করে। একটি গণনার গণনা করতে, আপনি প্রায়শই একটি foreach
লুপ ব্যবহার করেন । তবে একটি foreach
লুপ সিনট্যাকটিক চিনিও। সুতরাং আপনি দুটি বিমূর্ততা রিয়েল কোড থেকে সরিয়েছেন যার কারণে এটি প্রাথমিকভাবে বুঝতে পারে যে এটি কীভাবে সমস্ত একসাথে কাজ করে।
ধরে নিন যে আপনার খুব সাধারণ পুনরাবৃত্তকারী ব্লক রয়েছে:
IEnumerable<int> IteratorBlock()
{
Console.WriteLine("Begin");
yield return 1;
Console.WriteLine("After 1");
yield return 2;
Console.WriteLine("After 2");
yield return 42;
Console.WriteLine("End");
}
রিয়েল ইটারেটর ব্লকগুলিতে প্রায়শই শর্ত এবং লুপ থাকে তবে আপনি যখন শর্তগুলি পরীক্ষা করেন এবং লুপগুলি আনرول করেন তখন তারা yield
অন্য কোডের সাথে ইন্টারলিভ থাকা স্টেটমেন্ট হিসাবে শেষ হয় ।
foreach
পুনরাবৃত্তকারী ব্লক গণনা করতে একটি লুপ ব্যবহৃত হয়:
foreach (var i in IteratorBlock())
Console.WriteLine(i);
এখানে আউটপুট (এখানে কোনও আশ্চর্যের কিছু নেই):
শুরু করা
1
After এর পরে
2
2 পরে
42
শেষ
উপরে উল্লিখিত হিসাবে foreach
সিনট্যাকটিক চিনি:
IEnumerator<int> enumerator = null;
try
{
enumerator = IteratorBlock().GetEnumerator();
while (enumerator.MoveNext())
{
var i = enumerator.Current;
Console.WriteLine(i);
}
}
finally
{
enumerator?.Dispose();
}
এটি আনুষঙ্গিক করার প্রয়াসে আমি বিমূর্ততাগুলি সরানোর সাথে একটি ক্রম ডায়াগ্রাম আঁকিয়েছি:
সংকলক দ্বারা উত্পাদিত রাষ্ট্রযন্ত্রটিও গণকের প্রয়োগ করে তবে চিত্রটি আরও স্পষ্ট করতে আমি তাদের পৃথক দৃষ্টান্ত হিসাবে দেখিয়েছি। (যখন রাষ্ট্রীয় মেশিনটি অন্য থ্রেড থেকে অঙ্কিত হয় আপনি আসলে পৃথক দৃষ্টান্ত পান তবে সে বিবরণটি এখানে গুরুত্বপূর্ণ নয়))
প্রতিবার আপনি যখন আপনার পুনরাবৃত্তকারীকে ব্লক করেন তখন রাষ্ট্র মেশিনের একটি নতুন উদাহরণ তৈরি হয়। তবে, পুনরুক্তিকারী ব্লকের কোনও কোডই enumerator.MoveNext()
প্রথমবার কার্যকর না হওয়া পর্যন্ত কার্যকর করা হয় না । এভাবেই স্থগিত কার্যকর করা কাজ করে। এখানে একটি (বরং নির্বোধ) উদাহরণ:
var evenNumbers = IteratorBlock().Where(i => i%2 == 0);
এই সময়ে পুনরুক্তি কার্যকর করা হয়নি। Where
দফা একটি নতুন সৃষ্টি IEnumerable<T>
যে গোপন IEnumerable<T>
দ্বারা ফিরে IteratorBlock
কিন্তু এই গণনীয় এখনো গণিত করতে হবে। আপনি যখন foreach
লুপটি কার্যকর করেন তখন এটি ঘটে :
foreach (var evenNumber in evenNumbers)
Console.WriteLine(eventNumber);
যদি আপনি গণনার দ্বিগুণ হন তবে প্রতিবারের মতো রাষ্ট্র মেশিনের একটি নতুন উদাহরণ তৈরি হয় এবং আপনার পুনরাবৃত্তকারী ব্লক একই কোডটি দু'বার কার্যকর করবে।
লক্ষ করুন যে, LINQ পদ্ধতি পছন্দ ToList()
, ToArray()
, First()
, Count()
ইত্যাদির ব্যবহার করবে foreach
লুপ গণনীয় গনা। উদাহরণস্বরূপ, ToList()
গণনার সমস্ত উপাদান গণনা করা হবে এবং সেগুলি একটি তালিকায় সংরক্ষণ করবে। পুনরাবৃত্তির পুনরায় কার্যকরকরণ ব্যতীত গণনার সমস্ত উপাদান পাওয়ার জন্য আপনি এখন তালিকাটি অ্যাক্সেস করতে পারেন। সেখানে একটি ট্রেড বন্ধ CPU- র ব্যবহার গণনীয় একাধিক বার উপাদান উত্পাদন করতে এবং মেমরি যখন মত পদ্ধতি ব্যবহার করে তাদের একাধিক বার অ্যাক্সেস করতে শুমার উপাদান সংরক্ষণ করতে মধ্যে ToList()
।