কি "ফলন বিরতি;" সি # তে করেন?


493

আমি এমএসডিএন-তে এই বাক্য গঠনটি দেখেছি: yield breakতবে এটি কী করে তা আমি জানি না। কেউ কি জানে?


26
তবুও, এমএসডিএন ডকুমেন্টেশনগুলি এর উল্লেখ করেছে তবে এটি ব্যাখ্যা করে না। জ্ঞান ক্ষুধার্ত বিকাশকারীকে জ্বালাতন করার এটি একটি খারাপ উপায়।
ফিল

3
ফলন রিটার্ন একটি ব্যাকিং তালিকার প্রয়োজনকে সরিয়ে দেয়, এটি হ'ল আপনার মতো কিছু করার দরকার MyList.Add(...)নেই yield return ...। আপনার যদি অকাল থেকে লুপটি ভেঙে ফেলার প্রয়োজন হয় এবং আপনি যে ভার্চুয়াল ব্যাকিং yield break;
লিস্টটি

উত্তর:


529

এটি নির্দিষ্ট করে যে কোনও পুনরাবৃত্তির অবসান হয়েছে। আপনি 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");

এই ক্ষেত্রে সর্বশেষ বিবৃতি কখনই কার্যকর করা হয় না কারণ আমরা প্রথমদিকে ফাংশনটি রেখে দিয়েছি।


8
এটি উপরে আপনার উদাহরণের breakপরিবর্তে কেবল হতে পারে yield break? সংকলক তাতে অভিযোগ করে না।
ওরাড

85
breakএই ক্ষেত্রে @ সরল একটি সাধারণ লুপটি থামিয়ে দেবে, তবে এটি পদ্ধতিটি কার্যকর করা বাতিল করবে না, সুতরাং শেষ পংক্তিটি কার্যকর হবে এবং "আমাকে দেখবেন না" পাঠানোটি আসলে দেখা যাবে।
দামির জেকিć

5
@ দামির জেকিć আপনি কি নিজের উত্তরে যুক্ত করতে পারেন কেন আপনার প্রত্যাশার তুলনায় ফলন বিরতি কেন পছন্দ করা উচিত এবং দুজনের মধ্যে পার্থক্য কী?
ব্রুনো কস্তার

11
@ দামিরজেকিć নাল এবং ফলের ফলন ফিরে আসার মত নয় । আপনি যদি শূন্য হয়ে ফিরে যান তবে আপনার NullReferenceExceptionকাছে আইনামেবলের এনুমरेटर পাওয়া যাবে, ফলন বিরতির সাথে আপনি কী করবেন না (কোনও উপাদান নেই এমন উদাহরণ রয়েছে)।
ব্রুনো কস্তা

6
@ ব্রুনো কোস্টা একই পদ্ধতিতে নিয়মিত আয় করার চেষ্টা করা একটি সংকলক ত্রুটি দেয়। yield return xসতর্কতা সংকলক ব্যবহার করে আপনি এই পদ্ধতিটি কোনও Enumeratorবস্তু তৈরির জন্য সিনট্যাকটিক চিনি হতে চান । এই গণকের পদ্ধতি MoveNext()এবং সম্পত্তি রয়েছে Current। মুভনেক্সট () একটি yield returnবিবৃতি না হওয়া পর্যন্ত পদ্ধতিটি কার্যকর করে এবং সেই মানটিকে রূপান্তর করে Current। পরের বার মুভনেসেক্স্ট ডাকা হবে, সেখান থেকে কার্যকর করা চলতে থাকবে। yield breakকারেন্টটি শূন্যে সেট করে, এই গণকের শেষের সংকেত দেয়, যাতে একটি foreach (var x in myEnum())শেষ হয়।
ওল্ফজুন

57

একটি পুনরাবৃত্তকারী ব্লক শেষ করে (উদাঃ আইকনামারেবলের মধ্যে আরও কোনও উপাদান নেই)।


2
[+1] সহ - যদিও একাডেমিকভাবে NET- তে কোনও পুনরাবৃত্তিকারী নেই। কেবল গণনাকারী (এক দিক, এগিয়ে)
শন উইলসন

@ শন উইলসন, তবে yieldকীওয়ার্ডের সাহায্যে আপনি উভয় দিক থেকে সংগ্রহটি পুনরাবৃত্তি করতে পারবেন, তদুপরি আপনি সংগ্রহের প্রতিটি উপাদান একটি সারিতে নাও নিতে পারেন
মঙ্গলবার

@ মমস্ট্রো আপনি যে কোনও ফ্যাশনে সংগ্রহ পুনরাবৃত্তি করতে পারেন এবং yieldএটি করার দরকার নেই। আমি বলছি না যে আপনি ভুল, আমি দেখতে পাচ্ছি আপনি কী পরামর্শ দিচ্ছেন; কিন্তু, একাডেমিকভাবে .NET- তে কোনও পুনরাবৃত্তকারী নেই, কেবল গণক (এক দিক, এগিয়ে) - স্টাডিসি ++ এর বিপরীতে সিটিএস / সিএলআর-তে কোনও "জেনেরিক ইটারেটর ফ্রেমওয়ার্ক" সংজ্ঞায়িত করা হয়নি। লিনকিউ এক্সটেনশন পদ্ধতিগুলির সাথে ব্যবধানটি বন্ধ করতে সহায়তা করে yield return যা কলব্যাক পদ্ধতিগুলি ব্যবহার করে এবং এটি প্রথম শ্রেণির এক্সটেনশন পদ্ধতি, প্রথম শ্রেণির পুনরাবৃত্তিকারী নয়। IEnumerableকলকারীকে ফরোয়ার্ড আর্ট করা ব্যতীত অন্য কোনও দিক থেকে ফলাফল নিজেই পুনরাবৃত্তি করতে পারে না।
শন উইলসন

29

পুনরাবৃত্তিকে বলে যে এটি শেষ পর্যন্ত পৌঁছেছে।

উদাহরণ হিসাবে:

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;
    }
}

21

yieldমূলত একটি IEnumerable<T>পদ্ধতিটি একটি সমবায়ভাবে পূর্বনির্ধারিত থ্রেডের সাথে সমানভাবে আচরণ করে।

yield returnসিপিইউর নিয়ন্ত্রণ ছেড়ে দেওয়ার জন্য "সূচি" বা "ঘুম" ফাংশন হিসাবে ডাকে এমন থ্রেডের মতো। একটি থ্রেডের মতোই, IEnumerable<T>পদ্ধতিটি ঠিক পরে বিন্দুতে নিয়ন্ত্রণগুলি ফিরে পায়, সমস্ত স্থানীয় ভেরিয়েবলগুলির নিয়ন্ত্রণ সমাপ্তির আগে তার মানগুলির সমান হয়।

yield break এটি তার ফাংশনটির শেষে এবং সমাপ্তির মতো থ্রেডের মতো।

লোকেরা একটি "রাষ্ট্রীয় মেশিন" সম্পর্কে কথা বলে তবে একটি রাষ্ট্রীয় মেশিনটি সমস্ত "থ্রেড" আসলেই। একটি থ্রেডের কিছু স্টেট থাকে (স্থানীয় ভেরিয়েবলের অর্থ), এবং প্রতিটি সময় নির্ধারিত হয়ে গেলে এটি একটি নতুন অবস্থায় পৌঁছাতে কিছু পদক্ষেপ গ্রহণ করে। মূল বিষয়টি yieldহ'ল আমরা যে অপারেটিং সিস্টেমের থ্রেডগুলির ব্যবহার করি তার বিপরীতে, কোডটি যা ব্যবহার করে তা পুনরুক্তি ম্যানুয়ালি উন্নত বা সমাপ্ত না হওয়া পর্যন্ত সময়ে হিমায়িত হয়।


13

জন স্কিটের গভীরতাতে সি # বইয়ের এই নিখরচায় নমুনা অধ্যায়ে পুনরাবৃত্তকারী ব্লকগুলির পুরো বিষয়টি ভালভাবে কভার করা হয়েছে


আপনি আমাকে একটি অনুলিপি বিক্রি করেছেন। ধন্যবাদ! :-)
জন স্নাইডার

9

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.");
}

উপরের উদাহরণে, পুনরুদ্ধারকারী পদ্ধতিটি maxCountপ্রাইমগুলি পাওয়া গেলে স্বাভাবিকভাবেই সম্পাদন বন্ধ করে দেবে ।

yield breakবিবৃতি পুনরুক্তিকারীর enumerating বন্ধ করতে আরেকটি উপায়। এটি প্রথম দিকে গণনা থেকে বেরিয়ে আসার একটি উপায়। এখানে উপরের মত একই পদ্ধতি। এবার, পদ্ধতিটি কার্যকর করতে পারে এমন পরিমাণের একটি পদ্ধতি রয়েছে।

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(..)


7

এখানে http://www.alteridem.net/2007/08/22/the-yeld-statement-in-c/ খুব ভাল উদাহরণ:

পাবলিক স্ট্যাটিক আইমুনামেবল <দন্ত> ব্যাপ্তি (অন্তর্নিহিত মিনিট, অন্তত সর্বাধিক)
{
   যখন (সত্য)
   {
      যদি (সর্বনিম্ন> = সর্বাধিক)
      {
         ফলন বিরতি;
      }
      ফলন মিনিট ++;
   }
}

এবং ব্যাখ্যা, যে যদি কোনও yield breakপদ্ধতির মধ্যে কোনও বিবৃতি আঘাত করা হয়, তবে সেই পদ্ধতিটি কার্যকর করা কোনও রিটার্ন ছাড়াই বন্ধ হয়ে যায়। কিছু সময়ের পরিস্থিতি রয়েছে, যখন আপনি কোনও ফল দিতে চান না, তখন আপনি ফলন বিরতি ব্যবহার করতে পারেন।


5

ফলন বিরতি হ'ল শেষ বারের জন্য রিটার্ন বলার উপায় এবং কোনও মান ফেরত দেবে না

যেমন

// 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;
 }

4

যদি "ফলন বিরতি আসলে কী করে" বলতে বোঝায়, তবে এটি "এটি কীভাবে কাজ করে" - বিশদ বিবরণের জন্য রেমন্ড চেনের ব্লগটি দেখুন https://devblogs.microsoft.com/oldnewthing/20080812-00/?p=21273

সি # পুনরাবৃত্তিকারীরা খুব জটিল কিছু কোড উত্পন্ন করে।


12
ঠিক আছে, আপনি যদি সেগুলি সংকলিত কোডটির প্রতি যত্নশীল হন তবে এগুলি কেবল জটিল। এগুলি ব্যবহার করে এমন কোডটি খুব সহজ।
রবার্ট রসনি

@ রবার্ট, এটাই আমি বোঝাতে চেয়েছিলাম তাই আমি আপনার মন্তব্য অন্তর্ভুক্ত করার জন্য উত্তরটি আপডেট করেছি
টনি লি

-2

ফলন কীওয়ার্ডটি ফেরত কীওয়ার্ডের সাথে একত্রে গণকের অবজেক্টকে একটি মান সরবরাহ করতে ব্যবহৃত হয়। ফলন ফেরত মান বা মানগুলি নির্দিষ্ট করে দেয় returned ফলন ফেরতের বিবৃতি পৌঁছে গেলে বর্তমান অবস্থানটি সংরক্ষণ করা হয়। পরের বার পুনরুক্তিকারীকে ডাকা হলে এই অবস্থান থেকে পুনরায় কার্যকর করা হবে।

একটি উদাহরণ ব্যবহার করে অর্থ ব্যাখ্যা করতে:

    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 ছিল।


11
আপনি কী yield breakকরেন তা ব্যাখ্যা করেননি
জে সুলিভান

আমি মনে করি না যে yield returnবাস্তবে একাধিক মান ফিরিয়ে দেওয়া সমর্থন করে। আপনি সম্ভবত এটি বোঝাতে চেয়েছিলেন না, তবে আমি এটি এটিই পড়ি।
স্যাম

স্যাম - একাধিক ফলন ফেরতের বিবৃতি সহ নমুনা নম্বর পদ্ধতি বাস্তবে কাজ করে, পুনরাবৃত্তির মান অবিলম্বে ফিরে আসে এবং পরবর্তী মানটির অনুরোধ করা হলে মৃত্যুদন্ড কার্যকর করা হয়। আমি লোকদের "ফলন বিরতি" দিয়ে একটি পদ্ধতি শেষ করতে দেখেছি, তবে এটি অপ্রয়োজনীয়। পদ্ধতির শেষে আঘাত করা পুনরাবৃত্তিরও শেষ করে
লরেন পলসেন 16:51

yield breakএটির জন্য এটি একটি দুর্বল উদাহরণ হ'ল কারণ এটিতে কোনও ভাষা-স্তরের গণক থাকে না যেমন foreach- একটি গণক ব্যবহারের সময় yield breakপ্রকৃত মান সরবরাহ করে। এই উদাহরণটি একটি অনিবন্ধিত লুপের মতো দেখাচ্ছে। আপনি বাস্তব কোডটি এই কোডটি প্রায় কখনও দেখতে পাবেন না (আমরা সকলেই কিছু প্রান্তের কেসগুলি সম্পর্কে নিশ্চিত ভাবতে পারি), এছাড়াও এখানে "পুনরাবৃত্তি" নেই। "পুনরাবৃত্তকারী ব্লক" ভাষা নির্দিষ্টকরণের বিষয়টি হিসাবে পদ্ধতিটির বাইরে প্রসারিত করতে পারে না। আসলে যা ফিরিয়ে দেওয়া হচ্ছে এটি একটি "গণনাযোগ্য", এটিও দেখুন: স্ট্যাকওভারফ্লো.com
শান উইলসন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.